Table of contents for AS3 Avoider Game Tutorial
- Learn ActionScript 3 by Following this Simple Avoider Game Tutorial
- AS3 Avoider Game Tutorial, Part 2: Multiple Enemies
- AS3 Avoider Game Tutorial, Part 3: Game Over
- AS3 Avoider Game Tutorial, Part 4: Menus and Buttons
- AS3 Avoider Game Tutorial, Part 5: A Score and a Clock
- AS3 Avoider Game Tutorial, Part 6: Several Small Improvements
- AS3 Avoider Game Tutorial, Part 7: Keyboard Control
- AS3 Avoider Game Tutorial, Part 8: Adding a Preloader
- AS3 Avoider Game Tutorial, Part 9: Music and Sound Effects
- AS3 Avoider Game Tutorial, Part 10: Multiple Levels
- AS3 Avoider Game Tutorial, Part 11: Saving and Loading
- AS3 Avoider Game Tutorial, Part 12: Garbage Collection
In this part of my AS3 and Flash CS3 conversion of Frozen Haddock’s avoider game tutorial, we’ll add keyboard controls. Don’t worry, we’ll keep the code separate so that it won’t interfere with the mouse controls we’ve already put in!
Click the image below to see how this will play:
If you’ve not been following the tutorial, grab the zip file of the game so far here and extract it somewhere. Otherwise, copy the files you’ve been working on so far to a new folder, as usual.
Open the FLA file, and let’s get started.
Switching Control Schemes
Rather than removing the mouse controls entirely, let’s set things up so that we can switch between the two control schemes easily. Open AvoiderGame.as, and create a new Boolean variable at the class level named useMouseControl:
8 9 10 11 12 13 14 | public class AvoiderGame extends MovieClip { public var army:Array; public var enemy:Enemy; public var avatar:Avatar; public var gameTimer:Timer; public var useMouseControl:Boolean; |
Remember, a Boolean is a variable that can only be one of two values: true or false. We’re going to use it as a “toggle”; if it’s true, mouse controls will work and keyboard controls won’t; if it’s false, keyboard controls will work and mouse controls won’t.
Since we haven’t written the keyboard control code yet, let’s set it to true so that we can test it out. The constructor is a fine place to do this:
16 17 18 | public function AvoiderGame() { useMouseControl = true; |
Since useMouseControl is defined at the class level, it’ll be available throughout AvoiderGame.
At the moment, there are only two places where we’re referring to the mouse’s position in code. The first is in the constructor, where we set the initial position of the avatar to be wherever the cursor is:
25 26 27 28 | avatar = new Avatar(); addChild( avatar ); avatar.x = mouseX; avatar.y = mouseY; |
If the player’s not using the mouse to control the game, it’s going to be pretty annoying for them to have the avatar start out wherever the mouse happens to be. Let’s change that:
25 26 27 28 29 30 31 32 33 34 35 36 | avatar = new Avatar(); addChild( avatar ); if ( useMouseControl ) { avatar.x = mouseX; avatar.y = mouseY; } else { avatar.x = 200; avatar.y = 250; } |
The code in the else section is only going to be run if the player is using keyboard control, and will place the avatar at the bottom-centre of the screen (adjust the numbers depending on what you think is best).
Before we test this, let’s change the other bit of code that references the mouse. It’s in the onTick() function and it’s exactly the same:
54 55 | avatar.x = mouseX; avatar.y = mouseY; |
Not surprisingly, our change will be very similar to before:
54 55 56 57 58 59 60 61 62 | if ( useMouseControl ) { avatar.x = mouseX; avatar.y = mouseY; } else { //no keyboard code yet! } |
(Remember, line 61 is a comment and will be ignored by Flash; it’s just there as a reminder to us.)
If you save this and run it… well, you won’t see anything different, because we’ve set useMouseControl to true. That’s good, it means we can do whatever we like regarding keyboard control and it won’t mess up our existing mouse control code.
Change useMouseControl to false (in the constructor) and run it again.

You’ll find the avatar starts at the bottom-centre of the screen and cannot be moved by the mouse. Great! Well, not so great for the player. But we’ll fix that.
Going Down
Remember when we first programmed the Enemy, and wrote the function moveDownABit()? By increasing the y-position of the enemy a little bit every tick, we simulated downwards motion. Let’s use the same strategy for the Avatar. Open up Avatar.as. It’s almost entirely empty — how exciting:
1 2 3 4 5 6 7 8 9 10 11 | package { import flash.display.MovieClip; public class Avatar extends MovieClip { public function Avatar() { } } } |
Add the new function:
6 7 8 9 10 11 12 13 14 | public function Avatar() { } public function moveDownABit():void { y = y + 2; } |
Yep, this goes against what I said in the last part about hard-coding values. Don’t worry, we’ll change it soon.
The enemy objects have their movement functions called exactly once per tick. We need to call the appropriate movement functions for the avatar once per tick… but how do we know when it’s appropriate?
Ideally, we’d do something like this (in the onTick() function):
54 55 56 57 58 59 60 61 62 63 64 65 | if ( useMouseControl ) { avatar.x = mouseX; avatar.y = mouseY; } else { if ( downKeyIsBeingPressed ) { avatar.moveDownABit(); } } |
In AS2 we could have done exactly that — but not in AS3. Now we’re living in the futuristic world of Events, and we have to do a little more to make this work.
You see, we can’t detect whether a given key is being pressed at a given time — that functionality is gone. But with event listeners, we can detect when a given key has been pushed down, and we can also detect when a given key has been lifted up again. If we have detected that a key has been pushed down and we have not yet detected that the same key has been lifted up, well, it’s a pretty safe bet that the key is being pushed down at that very moment, right?
[If this isn't clear, imagine that every time you press the B key, your computer says aloud "the B key has just been pressed", and every time you take your finger off the B key, your computer says "the B key is no longer being pressed". Someone listening to your computer would have a pretty good idea of whether or not you were pushing the B key even if they weren't looking at your hands.]
Enough talk. Let’s get the code in.
First, we need another Boolean to take note of whether the Down key is currently being pressed. Let’s call it downKeyIsBeingPressed. It needs to go in AvoiderGame.as, at the same places where we set up useMouseControl:
14 15 16 17 18 19 20 | public var useMouseControl:Boolean; public var downKeyIsBeingPressed:Boolean; public function AvoiderGame() { downKeyIsBeingPressed = false; useMouseControl = false; |
(I’m assuming here that the player isn’t holding down the Down key as he starts the game.)
Now we need to detect when the player is pressing and releasing keys. You will probably not be surprised to find that we use event listeners for this. This should all be very simple to do, but unfortunately (and despite keyboard control being a Very Useful Feature for a lot of applications) Flash seems to go out of its way to make things confusing. Please bear with me through this next section, it’s not hard, just irritating
Flash vs. Developers
Let’s start by adding the event listeners. Add these lines to the end of the AvoiderGame.as constructor function:
44 45 | addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress ); addEventListener( KeyboardEvent.KEY_UP, onKeyRelease ); |
Guess what? Yep, Flash needs to be told about KeyboardEvent, so import it at the top:
3 4 5 6 7 | import flash.display.MovieClip; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Mouse; import flash.events.KeyboardEvent; |
First we’ll create the onKeyPress event listener, which will be triggered whenever a key is pushed down:
49 50 51 52 | public function onKeyPress( keyboardEvent:KeyboardEvent ):void { } |
(Remember to create this outside of the constructor function but inside the class.)
How do we know which key is being pressed? Well, every key has a unique ID number, called a key code, and the event object stores the key code of whichever key triggered the event. Obviously it would be inconvenient if we had to remember every single ID, so Flash helps us out by giving us a class, Keyboard, that stores all these codes.
Of course, we have to import it:
3 4 5 6 7 8 | import flash.display.MovieClip; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Mouse; import flash.events.KeyboardEvent; import flash.ui.Keyboard; |
Go back to the onKeyPress event handler and add the following:
50 51 52 53 54 55 56 | public function onKeyPress( keyboardEvent:KeyboardEvent ):void { if ( keyboardEvent.keyCode == Keyboard.DOWN ) { downKeyIsBeingPressed = true; } } |
If you’re using Flash to write your AS files, then as soon as you type Keyboard. you’ll see a big list of all the different keys available appear.
The onKeyRelease event listener is very similar:
58 59 60 61 62 63 64 | public function onKeyRelease( keyboardEvent:KeyboardEvent ):void { if ( keyboardEvent.keyCode == Keyboard.DOWN ) { downKeyIsBeingPressed = false; } } |
Obviously it’s very important to have downKeyIsBeingPressed set to false here and true above.
Alright, so, in theory we should now be able to tell whether the Down key is currently being pressed from any point within AvoiderGame. This means we can add in our ideal code from earlier to the onTick() function:
77 78 79 80 81 82 83 84 85 86 87 88 | if ( useMouseControl ) { avatar.x = mouseX; avatar.y = mouseY; } else { if ( downKeyIsBeingPressed ) { avatar.moveDownABit(); } } |
If you save it and run it this will not work. Sorry. We have to make a couple of changes first.
For one thing, Keyboard Event listeners have to be added to the stage. To quote the AS3 LiveDocs: “The Stage class represents the main drawing area. The Stage represents the entire area where Flash® content is shown.”
Simple enough. Go back to the constructor function and change the addEventListener calls from this:
47 48 | addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress ); addEventListener( KeyboardEvent.KEY_UP, onKeyRelease ); |
to this:
47 48 | stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress ); stage.addEventListener( KeyboardEvent.KEY_UP, onKeyRelease ); |
Will this work now? No, we’ll get an error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
The problem is, stage is actually null at this point. Why? Well, an object only has access to stage if it’s been addChild-ed to the document class, or to another object that has been addChild-ed to the document class or… etc. But look at the code in DocumentClass.as:
40 41 42 43 44 | playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); playScreen.x = 0; playScreen.y = 0; addChild( playScreen ); |
The AvoiderGame() constructor function — and therefore the stage.addEventListener() lines — is run when new AvoiderGame() is run. But the addChild( playScreen ) line — which is required for playScreen to actually have a stage — isn’t run until after that point.
We get around this by using another event listener. This one is going to be triggered when that addChild( playScreen ) line is called. We can then add the stage.addEventListener() lines within that event handler. Confusing? Let’s write the code, it’ll make it clearer.
First, in AvoiderGame.as, replace
47 48 | stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress ); stage.addEventListener( KeyboardEvent.KEY_UP, onKeyRelease ); |
with
46 | addEventListener( Event.ADDED_TO_STAGE, onAddToStage ); |
(Don’t delete the onKeyPress and onKeyRelease event handler functions, we’ll need them later!)
Naturally we need to import this Event class…
3 4 5 6 7 8 9 | import flash.display.MovieClip; import flash.utils.Timer; import flash.events.TimerEvent; import flash.ui.Mouse; import flash.events.KeyboardEvent; import flash.ui.Keyboard; import flash.events.Event; |
Now, create a new event handler for this Event.ADDED_TO_STAGE event:
50 51 52 53 54 | public function onAddToStage( event:Event ):void { stage.addEventListener( KeyboardEvent.KEY_DOWN, onKeyPress ); stage.addEventListener( KeyboardEvent.KEY_UP, onKeyRelease ); } |
Save it and run it. Hooray, it works!
Although… try pressing any of the other keys on the keyboard while the game is running. You’ll probably notice the mouse flashing to different symbols. If you have the FLA open, rather than an AS file, you’ll be able to see the different buttons in the toolbar being selected as you press different letter keys.
This is another of Stephen Calender’s obstacles for Flash game development, and it’s incredibly irritating if you want to use keys that also happen to be used by Flash. Fortunately, there is a solution. When your game is running, click Control > Disable Keyboard Shortcuts:

Voilà, no more problems.
[Jake let me know that this behaviour still exists in CS4 -- but luckily, so does the solution.]
Four-Way Movement
It’s now pretty simple to set the code up to detect other keys. Just take what we’ve already done and multiply it.
Class variables:
17 18 19 20 21 | public var useMouseControl:Boolean; public var downKeyIsBeingPressed:Boolean; public var upKeyIsBeingPressed:Boolean; public var leftKeyIsBeingPressed:Boolean; public var rightKeyIsBeingPressed:Boolean; |
Constructor function:
23 24 25 26 27 28 | public function AvoiderGame() { downKeyIsBeingPressed = false; upKeyIsBeingPressed = false; leftKeyIsBeingPressed = false; rightKeyIsBeingPressed = false; |
onKeyPress event handler:
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | public function onKeyPress( keyboardEvent:KeyboardEvent ):void { if ( keyboardEvent.keyCode == Keyboard.DOWN ) { downKeyIsBeingPressed = true; } else if ( keyboardEvent.keyCode == Keyboard.UP ) { upKeyIsBeingPressed = true; } else if ( keyboardEvent.keyCode == Keyboard.LEFT ) { leftKeyIsBeingPressed = true; } else if ( keyboardEvent.keyCode == Keyboard.RIGHT ) { rightKeyIsBeingPressed = true; } } |
I’ll leave you to figure out the onKeyRelease event handler
Perhaps you are thinking that I am a bit of a hypocrite, because back in Part 2 I said that it was bad to copy and paste code like that. Fair point! Actually, it would be much better to use an array of Booleans to store the states of every single key. I encourage you to have a go at that yourself (I did leave some hints in the comments of one of the earlier parts, if you get stuck). Alternatively, there’s a great piece of code here that’ll handle it all for you, the credit for which goes to the ever-excellent senocular. (If you’re having trouble getting this code to work, Monkeyman has written a great comment explaining what to do here.)
Now, I don’t fancy having four functions, moveDownABit(), moveUpABit(), etc., so I’m going to suggest we generalise moveDownABit(), just as we did with the Enemy code.
Go back to Avatar.as and change your moveDownABit() function to this:
11 12 13 14 15 | public function moveABit( xDistance:Number, yDistance:Number ):void { x += xDistance; y += yDistance; } |
We now need to pass the directions through from AvoiderGame.as, so reopen that file. Start by changing what we already had, from this:
109 110 111 112 | if ( downKeyIsBeingPressed ) { avatar.moveDownABit(); } |
to this:
109 110 111 112 | if ( downKeyIsBeingPressed ) { avatar.moveABit( 0, 3 ); } |
That’ll work, but we shouldn’t be writing “3″ explicitely, should we? Try this instead:
109 110 111 112 | if ( downKeyIsBeingPressed ) { avatar.moveABit( 0, 1 ); } |
And in Avatar.as:
11 12 13 14 15 16 | public function moveABit( xDistance:Number, yDistance:Number ):void { var baseSpeed:Number = 3; x += ( xDistance * baseSpeed ); y += ( yDistance * baseSpeed ); } |
See what we’re doing? If not, let’s add in the other three directions and make it a bit clearer. Go back to AvoiderGame.as:
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | if ( downKeyIsBeingPressed ) { avatar.moveABit( 0, 1 ); } else if ( upKeyIsBeingPressed ) { avatar.moveABit( 0, -1 ); } else if ( leftKeyIsBeingPressed ) { avatar.moveABit( -1, 0 ); } else if ( rightKeyIsBeingPressed ) { avatar.moveABit( 1, 0 ); } |
You see, the two parameters now define the direction of movement, rather than the speed. Speed is defined inside the Avatar class, which makes sense (and also follows the standard set by the Enemy class).
However, you can affect the relative speed of the avatar from the AvoiderGame class. For example, you could make WSAD the “walking” controls, which make the avatar move at half the speed, simply by adding lines like this:
if ( sKeyIsBeingPressed ) { avatar.moveABit( 0, 0.5 ); } |
Setting Some Boundaries
If you run the game now, you’ll see that it’s possible to move the avatar outside of the playing field, and therefore avoid all the enemies entirely!
To get round this, all we have to do is write some code to check, every tick, whether the avatar somewhere it shouldn’t be, and move it back into the playing field if so.
I think the best place for this is in AvoiderGame.as, in the onTick() function, immediately after all the code we’ve just written. Let me demonstrate with this code snippet:
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | if ( useMouseControl ) { avatar.x = mouseX; avatar.y = mouseY; } else { if ( downKeyIsBeingPressed ) { avatar.moveABit( 0, 1 ); } else if ( upKeyIsBeingPressed ) { avatar.moveABit( 0, -1 ); } else if ( leftKeyIsBeingPressed ) { avatar.moveABit( -1, 0 ); } else if ( rightKeyIsBeingPressed ) { avatar.moveABit( 1, 0 ); } } //we should check the avatar's position here //and move it if we need to var avatarHasBeenHit:Boolean = false; for each ( var enemy:Enemy in army ) { enemy.moveABit(); |
Where isn’t the avatar allowed? Let’s start with horizontal movement: the avatar can’t go left of the playing field. Now, we know that the left side of the play screen has an x-coordinate of zero (check the diagram in the first part of this tutorial for a reminder). So if the avatar’s x-coordinate is less than zero, it must be to the left of the play screen:
139 140 141 142 | if ( avatar.x < 0 ) { //avatar is left of play screen } |
What shall we do about it? It’s pretty simple — we just move the avatar back to the left edge:
139 140 141 142 | if ( avatar.x < 0 ) { avatar.x = 0; } |
Actually, because the avatar’s registration point is right in its centre, half-way across its width, this will let the avatar get half-way out of the screen:

You can keep it like this if you like, but I’d rather make sure the whole avatar was inside the screen. Fortunately this is easy too; we can just change our code like this:
139 140 141 142 | if ( avatar.x < ( avatar.width / 2 ) ) { avatar.x = avatar.width / 2; } |
If that’s confusing, just bear in mind that avatar.x refers to the x-coordinate of the centre of the avatar. The centre is, naturally, half a width away from the left-hand side. (Of course, if your avatar’s registration point isn’t centred, you’ll have to measure the distance yourself.)
This makes the avatar stop at the left side of the screen as if it were a wall:

The other three directions can be added similarly:
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | if ( avatar.x < ( avatar.width / 2 ) ) { avatar.x = avatar.width / 2; } if ( avatar.x > 400 - ( avatar.width / 2 ) ) { avatar.x = 400 - ( avatar.width / 2 ); } if ( avatar.y < ( avatar.height / 2 ) ) { avatar.y = avatar.height / 2; } if ( avatar.y > 300 - ( avatar.height / 2 ) ) { avatar.y = 300 - ( avatar.height / 2 ); } |
The numbers 400 and 300 are the width and height of my game. Bonus points for you if you use the soft-coding tip I talked about in Part 6 instead
Challenges
We’re getting to the point now where you understand a lot of concepts, and it’s actually more beneficial for you to have a go at using them yourself rather than having someone else tell you every single step to take. If you’re lacking inspiration, here are some ideas to get you started.
How about changing the menu screen to have two buttons — one for mouse control, and one for keyboard control? Hint: pass the value of useMouseControl through the AvoiderGame() constructor, like we do with the enemy’s position in the Enemy() constructor.
You might have found that the game is considerably harder with keyboard controls than with mouse controls. How about altering the rate at which enemies appear if the player is using the keyboard?
You’ve got four-way movement sorted; now how about eight-way movement? Hint: you can check if ( ( downKeyIsPressed ) && ( leftKeyIsPressed ) ). Be careful — the Pythagorean Theorem tells us that if you move three pixels down and three pixels left within a single tick, you’ll travel further (and therefore faster) than if you just move three pixels down or three pixels left. How can you get around that? UPDATE: Rasmus Wriedt Larsen wrote a tutorial on doing exactly this. Check it out here.
It’s always irritating to have to switch between keyboard and mouse. Can you make it so that the Start and Restart buttons can be pressed by hitting the space bar?
Don’t forget to have a go at making an array of booleans to hold the state of all your keys at once, or to use senocular’s KeyboardObject class, as mentioned above.
If you’d like a hand with any of these challenges, stick a note in the comments box below. If you’ve got any of your own, I’d love to hear them
Wrapping Up
That’s it for this week. As usual you can grab the zip file here.
In Part 8, we’ll add a preloader, an essential requirement for any Flash game.

{ 227 comments… read them below or add one }
← Previous Comments
@Michael: That sounds like a good idea, and I’d love to do it, but we’ll see. I’m actually having trouble putting up my tutorials lately, as my internet connection has been all but completely unresponsive. It takes forever to accomplish anything, including uploading videos to Youtube. But there is a possibility of getting faster internet, so I’m hopeful things can get better.
Monkeyman´s last blog ..Python 3 Tutorial- 10 – If statement
Dang, Monkeyman, that’s irritating. I hope you get your internet sorted!
Hi,
I have a noob question :3 (I’m trying to figure out the Challenges).
I added a new button on the main screen, one to handle mouse controls, the other for keyboard.
And since we have a “public var useMouseControl:Boolean;” that pretty much controls if Mouse or keyboard is being used, I thought it would be an easy fix..
So in my DocumentClass.as i tried to change the “useMouseControl” value from true to false depending on what button i press. But I am unsure how to change that value from another class. Just typing “useMouseControl = true;” didn’t work.
But as soon as i typed “playScreen.useMouseControl = true;” it works. How come? I can understand if i have to type “AvoiderGame” before useMouseControl but why playScreen?
thanx
Hey Doom, good question.
Remember that
playScreenis an instance of theAvoiderGameclass.Think of it this way: if you want to control the
xproperty of a specific enemy, you don’t write:…you write:
…where
enemy(small “e”) is an instance of theEnemyclass.Does that help? We can talk about this some more if you like.
Hi,
Yeah I understand it a bit better now thanx
But I’m still curious of why the “playScreen” part has to be there at all.
I’m used to Lingo (script language to Macromedia Director), where i just say “global enemy” and the enemy value is accessible from anywhere. No need to type playScreen.Enemy. Just “Global enemy / enemy = 1″ etc.
So I find it confusing and a bit irritating if I have to locate exactly where a value is kept, if I wan’t to access it from another class :/ (is there a nice tutorial explaining in more depth how to use these things?
)
Hey Doom,
I’m working on it
I know this’ll sound like a lame answer, but basically… that’s just the way it is. AS2 had global variables, but in AS3 every variable belongs to an object, and every object is an instance of a class. (That’s why AS3 is called an “object oriented” programming language.)
As for it being confusing, think about this: imagine that I write “global x” inside Enemy and also inside Avatar. Then, in AvoiderGame, I write “x = 10;”. What’s that going to do?
Hi,
Ah ok i see. Well then i guess I’ll just have to learn how to use this system
Really good that you’re working on a tutorial, will help me alot to understand it better.
And yeah I agree that problems may occur when using globals (as in your example), but I always tend to make unique Globals. So if done right, it rarely causes any trouble
Big thanx for the awnsers!
Hi i have a problem because i tri to make what you said about change between keyboard and mouse with space bar so i add :
if( keyboardEvent.keyCode == Keyboard.SPACE) { useMouseControl = !useMouseControl; }in the onKeyPress Function so i can switch betweenkeyboard an mouse but my problem is that while i use the keyboard, the mouse still in the same place so when i change to mouse mi buddy jump from one place to another and i don’t find a function or a variable to make a function with that change the position of the mouse. Can you help me??
Thank a lot by the way!!
@Doom: Unique globals, okay, yeah, I guess that’d help
But what if you want to use the same files in different projects? Or to share files with other people?
@Nando: I’m a little confused about what you mean. When you’re using the keyboard, the avatar is still following the mouse? Is that right?
I’m going through your tutorials again… I worry that because I haven’t been using it, I won’t remember anything, but going through it again I find that I remember more and understand more every time.
I was trying to make the space bar start the game from the menu screen without looking at code I’ve already created, and happily I was successful. But I was having a weird problem, where even after the game started if I pressed the space bar the game would “restart” – or seem to, it was really just throwing another instance of playScreen on top of the one I was currently playing.
After reading your comments I think this is something that will be fixed in chapter 12 on focusing, but as a band-aid solution I changed my onStart function (within DocumentClass) to look like this:
public function onStart( navigationEvent:NavigationEvent ):void { if( playScreen == null ) { playScreen = new AvoiderGame(); playScreen.addEventListener( AvatarEvent.DEAD, onAvatarDeath ); addChild( playScreen );}
In that way I check if playScreen is still null, and only if it is will I create an instance of playScreen. Using trace() I can see that menuScreen is still ‘hearing’ me press the space bar, so it’s not a perfect solution…
Bigfoot´s last blog ..Update!
Pretty sure you hate me by now, but I have a question.
I was messing with the keyboard controls and such, and doing things my way (which makes things more complicated than they should be because I fail at this), I’ve come to the conclusion that some things aren’t needed…
anywho, the code in my playscreen class is:
It’s basically how you make the keyboard work, the if statements for the booleans seem pointless to me, why not just stick it in the other if statements?
package {public class PlayScreen extends MovieClip
{
public var avatar:Avatar;
public var gameTimer:Timer;
public var downIsPressed:Boolean;
public var upIsPressed:Boolean;
public var leftIsPressed:Boolean;
public var rightIsPressed:Boolean;
}
}
Sorry for the delay on these replies.
@Bigfoot: Bigfoot! Long time no speak — how’ve you been? Shoot me an email some time
Good call — this is something that will be addressed in Chapter 12. (It’s basically because the event listener gets attached to the
stage, rather than to the menu screen, and therefore remains even after the menu screen has been removed.) Cool solution though!@Josh: Haha not at all; questions are good. It’s great to see you experimenting with doing things your own way.
Interesting point. No, in this case, there’s no need to keep the if-checks for
downIsPressed,upIsPressed, etc. separate to the checks forkeyboardEvent.keyCode. My code differs a bit: the if-checks fordownIsPressed,upIsPressedetc. all cause the actual movement, and so should go in the onTick() function. In your code, they don’t cause the movement — I mean, they don’t call theavatar.moveABit()function — so they don’t need to go in onTick().You’ve still got the actual call to
avatar.moveABit()in onTick(), which is just as it should beHi, I know this is completely off topic, but can you explain:
rotation = Math.atan2(mouseY – y, mouseX – x) / Math.PI * 180;
to me?
I found it online as a way for an object to rotate to follow the mouse (it’s not actually working for me, but seeing as I don’t know what it’s doing I can’t actually try and fix it)
All I know is that it’s getting (I think) the tan of (mouseY-y)-(mouseX-x) then dividing it by pi and timesing it by 180… I assume the 180 is for the actual angle portion of getting a rotation number, but I don’t know how the rest of it works.
If you do happen to mind, can you point me to something to read about it?
Oops!
I actually found:
instanceNameOfArrowClip.onMouseMove = function() { this._rotation = Math.atan2(_root._ymouse - this._y, _root._xmouse - this._x) / Math.PI * 180; updateAfterEvent(); };But changed it to go into my “moveABit” function in the avatar class to what it is above.
Hey Josh,
I’ve actually written about angles before in a separate post: Angles in Flash. Check it out, and if it doesn’t answer your question, please post the same question in the comments of that post.
Hello Michael,
I have a question, but before I get to that I would like to comment on your tutorials. They are some of the best I’ve seen. Your explanations are clear and to the point (and you do not repeat yourself =] ).
Anyways I’ve made a couple of side scrollers and found this useful for setting the boundaries…
function checkKeys() { if(Key.isDown(Key.RIGHT) && spriteX < 510) { spriteX += steps; knight.legs.play(); } else if(Key.isDown(Key.LEFT) && spriteX > 40) { spriteX -= steps; knight.legs.play(); } if(Key.isDown(Key.UP) && arrowActive == false) { knight.arms.play(); attachMovie("arrow","arrows", 8); arrows._x = spriteX; arrows._y = spriteY + 50; arrowActive = true; } }510 is the right side of the stage and 40 is the left.
The way you showed it works great as well, but the constant bouncing back into the stage was annoying to me. I thought it would look better without the constant repositioning…
I tried implementing something like this on the avatar, but I failed =(
I tried placing these bounds in the onTick constructor, but like I said Fail. Could you give me some help?
Thank you
Ok so I fixed some things and realized that there is no constant bouncing… lol XD
But can you still explain to me why it won’t let me do it this way.
Hey Snowcap, thanks for the kind words!
Nice technique, separating the position from the object like that.
What’s your code for the avatar like at the moment? Why does it fail?
Hey Michael,
so this is the if statement in the onTick function that checks whether to use mouse controls or keyboard controls. avatarX and avatarY are public vars that I instantiated in the AvoiderGame class and they have the values of avatar.x and avatar.y respectively. winHeight = window height, winWidth = window width.
/* If useMouseControl is true then mouse controls are selected, Else keyeboard controls are selected.*/ if(useMouseControl) { avatar.x = mouseX; avatar.y = mouseY; } else { if(downKeyIsBeingPressed && avatarY < winHeight) { avatar.moveABit(0, 1); } else if(upKeyIsBeingPressed && avatarY > 0) { avatar.moveABit(0, -1); } else if(rightKeyIsBeingPressed && avatarX < winWidth) { avatar.moveABit(1, 0); } else if(leftKeyIsBeingPressed && avatarX > 0) { avatar.moveABit(-1, 0); } }Is it in the wrong if statements?
Thanks
Sorry for putting this into two comments, just realized I never explained how it was failing. At first avatar would just go out of bounds. Then I found the problem. Now its the issue where half of the avatar is in bounds and the other half is out. I’m pretty sure I need to use the avatar’s width / 2 and height / 2, but how would I put that in the if statement?
Thanks again =)
I’m having some trouble with getting the switch between keyboard and mouse control. I’m getting an error code “1180: Call to a possibly undefined method controlScheme” when I try to call the “controlScheme” function in the AvoiderGame.as file. Here are some code changes I’ve made below. If anyone could help, that would be great.
AvoiderGame.as
deleted line:
added function:
public function controlScheme (controlSchemeVar:Number) { if (controlSchemeVar == 1) { useMouseControl = true; } else if (controlSchemeVar == 2) { useMouseControl = false; }NavigationEvent.as
added:
MenuScreen.as
added where toggleKM is the instance name of my button to be pushed as a toggle between keyboard and mouse:
public function MenuScreen() { Mouse.show(); startButton.addEventListener( MouseEvent.CLICK, onClickStart ); toggleKM.addEventListener (MouseEvent.CLICK, onClickToggle); }added function:
public function onClickToggle (event:MouseEvent):void { dispatchEvent (new NavigationEvent (NavigationEvent.TOGGLE)); }DocumentClass.as
added class variable:
added to document class function:
added new public function:
public function onRequestToggle(navigationEvent:NavigationEvent):void { if (toggleVariable == 2) { toggleVariable -= 1; } else { toggleVariable += 1; } }Revised onRequestStart function:
public function onRequestStart( navigationEvent:NavigationEvent ):void {I’m almost there with this method but it doesn’t like my variable set up or something. I hope my code formatting worked for this post. If it would be better to email someone my file, I can do that too.
@Snowcap: How’s your algebra? You’re going to need it
(Hint: Remember that avatar.x (and avatarX) are set to the centre point of the avatar, not either edge.)
@Rootzm: Thanks for the detailed breakdown, makes it much easier!
You have the right idea, and you’re really close to getting this working. In fact, I think the only problem is in your
DocumentClass.onRequestStart()function, where you callcontrolScheme(toggleVariable). Calling it like that, it’s trying to runDocumentClass.controlScheme(toggleVariable), and that doesn’t exist — hence the error.I don’t want to spell it out because that would rob you of solving the last piece, so have another look at that line and let me know if you need another hint
Thank you for your help. That did the trick. I was not referencing the class before calling the function as you hinted. I ended up having another problem where I was trying to call AvoiderGame.controlScheme(toggleVariable). I wasn’t using the instance of the class instead of the class itself. Rookie mistake.
Now I’m trying to get the mouse/keyboard decision on an Options screen linked from the main menu. I got it semi-working but am having problems with the variables I assign getting wiped out as navigation screens get nulled (i think that’s what’s happening). I may just make a globalvariable class that doesn’t get nulled and see how it goes. Maybe not the most efficient? I need to read and research on it.
Anyway. I’m rambling. Thanks again for the help
Awesome
Hmm, not sure what you mean about the variables getting wiped out, but if the classes containing those vars get removed then yeah that could cause a problem.
I am beyond stuck on the first challenge. I don’t even know what the problem is to ask for help on. All it’s saying is 1120: Access of undefined property useMouseControl. I have no idea where to define it, I have no idea what’s going on.
Sorry to be such a noob, but please help :S
In AvoiderGame.as, under ta class functions, do ya have something like this?
public var useMouseControl:Boolean;
If ya don’t then ya need ta add that
(rereading articles help solve ta problem 90% of ta time!)
Mushyrulez´s last blog ..YA SUCK AT TYPING
Yeah I already had that in there. I’ve fiddled around and somehow managed to get it to the point where it’s not broken… but it’s not working still if you get what I mean. There are no compiler errors, but now both the “start with mouse” and “start with keyboard” buttons use the mouse.
I’ve reread the tutorial what seems like a thousand times, I just can’t seem to get Flash (CS4 for the record, so I don’t know if things are different) to understand that I want the “start with keyboard” button to use the keyboard!
← Previous Comments