Beginning Flash and ActionScript Game Programming Part 10: Input and Event Handling

Beginning Flash and ActionScript Game Programming Part 10: Input and Event Handling

In the previous sections, we looked at how to create graphics on screen using vector drawing.

In this section, we’ll look at Flash and Actionscript specific concepts, event handling, and keyboard and mouse input.

Events and Event Handling

In Actionscript, there is a concept called “event handling”. Basically that certain events can be dispatched for actions, such as if a key is pressed, and you create listeners that are able to “catch” the events after being fired, and handle them.

This lets us capture and handle keyboard and mouse input, as well as several other event types.

Handling Mouse Input

So lets start by moving the smiley face around on screen, using the mouse.

Modify your “Main.as” class to look like below.

Main.as

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/**
	 * ...
	 * @author Chris Moeller
	 */
	public class Main extends Sprite 
	{
		public var smiley_face:Sprite;
		public var smiley_is_cursor:Boolean;
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			smiley_is_cursor = true;
			
			smiley_face = new Sprite();
			addChild(smiley_face);
			
			//draw the main circle
			smiley_face.graphics.beginFill(0xffff00);
			smiley_face.graphics.lineStyle(10, 0x000000);
			smiley_face.graphics.drawCircle(800 / 2, 600 / 2, 300);
			smiley_face.graphics.endFill();
			
			//draw the eyes
			smiley_face.graphics.lineStyle(0);
			smiley_face.graphics.beginFill(0x000000);
			//left eye (from our perspective)
			smiley_face.graphics.drawEllipse(290, 150, 75, 110);
			
			//right eye (from our perspective)
			smiley_face.graphics.drawEllipse(450, 150, 75, 110);
			smiley_face.graphics.endFill();
			
			//draw the mouth
			
			//draw left curve
			smiley_face.graphics.lineStyle(7);
			smiley_face.graphics.moveTo(250, 340);
			//first two are anchor point, second two are destination
			smiley_face.graphics.curveTo(240, 380, 190, 380);
			
			//now lets draw the right curve
			smiley_face.graphics.moveTo(550, 340);
			smiley_face.graphics.curveTo(560, 380, 613, 380);
			
			//and draw the final mouth curve
			smiley_face.graphics.lineStyle(10);
			smiley_face.graphics.moveTo(233, 373);
			smiley_face.graphics.curveTo(400, 600, 567, 373);
			
			//now to add input
			//start with the mouse
			stage.addEventListener(MouseEvent.MOUSE_MOVE, MouseMoveSmiley);
			smiley_face.addEventListener(MouseEvent.CLICK, SelectSmiley);
		}
		public function MouseMoveSmiley(e:MouseEvent):void
		{
			if (smiley_is_cursor)
			{
				smiley_face.x = mouseX-smiley_face.width/2;
				smiley_face.y = mouseY - smiley_face.height / 2;
			}
		}
		public function SelectSmiley(e:MouseEvent):void 
		{
			if(smiley_is_cursor)
				smiley_is_cursor = false;				
			else
				smiley_is_cursor = true;	
		}
		
	}
	
}

I set it up now so that by default, the smiley face will follow the cursor, and be at the center. When you click on the smiley once, it will follow your cursor, but if already following, it will leave it in it’s place.

The new lines added are:

Line 14: ‘smiley_is_cursor’ is a variable created to keep track of whether the smiley face is following the mouse. If set to true, we’ll have it follow the mouse, or false, stay where it is.

Line 25: We set ‘smiley_is_cursor’ to true, so that initially the smiley face moves with the cursor, so people can see something working.

Line 65: We add a listener to our “stage” object. This object is setup by default by flash, and is basically the “top level” object in flash. So we add a listener to it to catch any movement on the flash window, and to call the function “MouseMoveSmiley” whenever the mouse moves (when the MOUSE_MOVE function fires).

Line 66: We add another listener for whenever a click is detected, but we add this one onto the smiley face sprite. This way, whenever the smiley face is clicked, it calls the “SelectSmiley” function.

Line 68: This function is called whenever the mouse is moved, and is required to have a ‘MouseEvent’ passed to it in the parameters.
Inside of here, we check to see if the smiley is set to the cursor, and if so, we set the x and y position of the smiley sprite to that of the mouse, and take away half the width and height so that the smiley face is centered around the mouse.

Line 76: This function is called whenever the smiley face has been clicked. It will check whether the ‘smiley_is_cursor’ variable is set to true, if so set it to false, otherwise set it to true. So everytime this function is called, it will basically flip between setting the smiley face to follow the cursor or stay in place.

Tutorial Demo

This is what this will look like when you compile:
(use mouse to move smiley face, click to place it, click on it again to move it around)

Handling Keyboard Input

Another way to move things around on screen is through keyboard input. It is common to use the arrow keys to move something around on screen, so we’ll use it to move our smiley around.

We’ll comment out the mouse input listeners, and instead make some keboard listeners and functions.

Main.as

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.ui.Keyboard;
	
	/**
	 * ...
	 * @author Chris Moeller
	 */
	public class Main extends Sprite 
	{
		public var smiley_face:Sprite;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			smiley_face = new Sprite();
			addChild(smiley_face);
			
			//draw the main circle
			smiley_face.graphics.beginFill(0xffff00);
			smiley_face.graphics.lineStyle(10, 0x000000);
			smiley_face.graphics.drawCircle(800 / 2, 600 / 2, 300);
			smiley_face.graphics.endFill();
			
			//draw the eyes
			smiley_face.graphics.lineStyle(0);
			smiley_face.graphics.beginFill(0x000000);
			//left eye (from our perspective)
			smiley_face.graphics.drawEllipse(290, 150, 75, 110);
			
			//right eye (from our perspective)
			smiley_face.graphics.drawEllipse(450, 150, 75, 110);
			smiley_face.graphics.endFill();
			
			//draw the mouth
			
			//draw left curve
			smiley_face.graphics.lineStyle(7);
			smiley_face.graphics.moveTo(250, 340);
			//first two are anchor point, second two are destination
			smiley_face.graphics.curveTo(240, 380, 190, 380);
			
			//now lets draw the right curve
			smiley_face.graphics.moveTo(550, 340);
			smiley_face.graphics.curveTo(560, 380, 613, 380);
			
			//and draw the final mouth curve
			smiley_face.graphics.lineStyle(10);
			smiley_face.graphics.moveTo(233, 373);
			smiley_face.graphics.curveTo(400, 600, 567, 373);
			
			smiley_face.scaleX = .1;
			smiley_face.scaleY = .1;
			smiley_face.x = 400;
			smiley_face.y = 300;
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyboardMoveSmiley);
		}

		public function KeyboardMoveSmiley(e:KeyboardEvent):void
		{
			if (e.keyCode==Keyboard.LEFT)
				smiley_face.x--;
			
			else if (e.keyCode==Keyboard.RIGHT)			
				smiley_face.x++;
			
			
			if (e.keyCode==Keyboard.UP)
				smiley_face.y--;
			
			else if (e.keyCode==Keyboard.DOWN)
				smiley_face.y++;

		}
		
	}
	
}

If you compile this- and hold down the arrow keys, you’ll see the smiley face moves around and rotates on screen.

The new tidbits are:

Line 7: We need to import ‘flash.ui.Keyboard’ to be able to refer to keypresses using ‘Keyboard.RIGHT’ instead of first needing to trace out the keycode, and refer to it by number (right is ==39) (thanks goes to ‘Innes’ for letting me know about this)

Line 64-67: These lines are just used to scale down the smiley face, and re-position it close to the center.

Line 69: Here we add the ‘KeyboardEvent.KEY_DOWN’ listener to the stage, so that whenever a key is pressed, it calls the function ‘KeyboardMoveSmiley’.

Line 72: This is the function called whenever a key is pressed. It checks which key has been pressed, and moves the smiley face sprite in that direction, with the left and right keys also rotating the sprite.

Now you can move sprites, or a simmilar type “moveclips” around on screen!

Tutorial Demo

This is what this will look like when you compile:
(click the flash window first, then HOLD DOWN the arrow keys to move the smiley face around on the screen)

Adding a Game Loop

One last thing I would like to add is being able to keep the sprite moving, so that it doesn’t have to have the key pressed down the entire time to move.

Main.as

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	
	/**
	 * ...
	 * @author Chris Moeller
	 */
	public class Main extends Sprite 
	{
		public var smiley_face:Sprite;
		public var smiley_speed:Point;
		
		public var left_down:Boolean;
		public var right_down:Boolean;
		public var up_down:Boolean;
		public var down_down:Boolean;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			left_down = false;
			right_down = false;
			up_down = false;
			down_down = false;
			
			smiley_face = new Sprite();
			addChild(smiley_face);
			
			//draw the main circle
			smiley_face.graphics.beginFill(0xffff00);
			smiley_face.graphics.lineStyle(10, 0x000000);
			smiley_face.graphics.drawCircle(800 / 2, 600 / 2, 300);
			smiley_face.graphics.endFill();
			
			//draw the eyes
			smiley_face.graphics.lineStyle(0);
			smiley_face.graphics.beginFill(0x000000);
			//left eye (from our perspective)
			smiley_face.graphics.drawEllipse(290, 150, 75, 110);
			
			//right eye (from our perspective)
			smiley_face.graphics.drawEllipse(450, 150, 75, 110);
			smiley_face.graphics.endFill();
			
			//draw the mouth
			
			//draw left curve
			smiley_face.graphics.lineStyle(7);
			smiley_face.graphics.moveTo(250, 340);
			//first two are anchor point, second two are destination
			smiley_face.graphics.curveTo(240, 380, 190, 380);
			
			//now lets draw the right curve
			smiley_face.graphics.moveTo(550, 340);
			smiley_face.graphics.curveTo(560, 380, 613, 380);
			
			//and draw the final mouth curve
			smiley_face.graphics.lineStyle(10);
			smiley_face.graphics.moveTo(233, 373);
			smiley_face.graphics.curveTo(400, 600, 567, 373);
			
			//now to add input
			
			smiley_face.scaleX = .1;
			smiley_face.scaleY = .1;
			smiley_face.x = 400;
			smiley_face.y = 300;
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyboardMoveSmiley);
			stage.addEventListener(KeyboardEvent.KEY_UP, KeyboardStopMoveSmiley);
			
			smiley_speed = new Point(0, 0);
			stage.addEventListener(Event.ENTER_FRAME, RunGame);
		}

		public function KeyboardMoveSmiley(e:KeyboardEvent):void
		{
			if (e.keyCode==Keyboard.LEFT)
				left_down = true;
			else if (e.keyCode==Keyboard.RIGHT)
				right_down = true;
			
			if (e.keyCode==Keyboard.UP)
				up_down = true;
			else if (e.keyCode==Keyboard.DOWN)
				down_down = true;
		}
		
		public function KeyboardStopMoveSmiley(e:KeyboardEvent):void
		{
			if (e.keyCode==Keyboard.LEFT)
				left_down = false;
			else if (e.keyCode==Keyboard.RIGHT)
				right_down = false;
			
			if (e.keyCode==Keyboard.UP)
				up_down = false;
			else if (e.keyCode==Keyboard.DOWN)
				down_down = false;
		}
		
		public function RunGame(e:Event):void
		{
			if (left_down && smiley_speed.x > -10)
				smiley_speed.x -= 5;
			if (right_down && smiley_speed.x < 10)
				smiley_speed.x += 5;
			if (up_down && smiley_speed.y > -10)
				smiley_speed.y -= 5;
			if (down_down && smiley_speed.y < 10)
				smiley_speed.y += 5;
				
			
			smiley_face.x += smiley_speed.x;
			smiley_face.y += smiley_speed.y;
			
			if (smiley_face.x < 0)
			{
				smiley_face.x = 0;
				smiley_speed.x *= -.5;
			}
			else if (smiley_face.x+smiley_face.width > 800)
			{
				smiley_face.x = 800-smiley_face.width;
				smiley_speed.x *= -.5;
			}
			
			if (smiley_face.y < 0)
			{
				smiley_face.y = 0;
				smiley_speed.y *= -.5;
			}
			else if (smiley_face.y+smiley_face.height > 600)
			{
				smiley_face.y = 600-smiley_face.height;
				smiley_speed.y *= -.5;
			}
			
			smiley_speed.y += 2;
			smiley_speed.x *= .95;
		}
		
	}
	
}

This is a relatively large update, which will allow the smiley face to act as if under gravity, move using the keys to go faster up to a point, bounce off the “walls”, and keep moving when the keys have been let go of.

Line 17: We create a Point variable, that will hold the x and y speed of the smiley face. A “Point” is just a variable with a x and y Number, so that we can use this variable to keep track of an x and y value.

Line 19-22: We create 4 new variables to hold whether one of the arrow keys is being held down.

Line 35-38: We set all the “keys down” to false at the beginning.

Line 83-84: We have to have a listener for both when a key is pressed down (so we can make sure to move the smiley), and when the key is let go of (so we no longer have to apply a speed to the smiley face).

Line 86: Initially, we set the speed of the smiley face to 0 in both the x and y direction – so that it is stopped.

Line 87: This is another listener we add to our stage. Every time the flash renders a frame, the function ‘RunGame’ will be called. By default flash is setup to render at 30 frames per second (fps).
This is known as our “main loop”, because it is a function that will be called continously throughout our program, with no end, but will update all of our objects (currently just the smiley face)

Line 90: This is our function for when a key has been pressed. It will set the variables we created earlier to ‘true’ if that key is held down

Line 103: This will do the opposite of the above function, setting our key down variables to “false”, so that the program will no longer see the keys as down.

Line 116: This function is our main loop, that will be called every frame, so 30x per second at the default settings (project->properties to change the framerate – if you ever need to).
We will use it to update the speed and position of our smiley face.

Line 118-125: Here we check if each key is down using the Boolean variables we created earlier. If they are down, and the speed of the smiley face in the same direction is less than 10, we’ll add 5 to the speed in that direction.

Line 128-129: Here we actually change the position of the smiley face, by adding whatever the current speed is to the position. If it has a negative ‘x’ speed, it will move towards the left, a negative ‘y’ speed, it will move towards the top.
NOTE: In programing, the top left corner is 0,0. Moving right, x increases, so the right direction makes x become more positive, and therefore moving left makes x become more negative.
Contrary to normal cartesian coodinates, down is positive and up is negative! So when you move something in the up direction, the y value becomes more negative, and therefore when moving down, the y value becomes more positive.

Line 131-135: Here we check if the smiley faces left side is going off the screen (0 is the left side of the screen). If so, we set the x position to be right at the left edge, and reverse and halve the speed, so it appears to bounce off the left side of the screen.

Line 136: We do the same thing as previously, but using the right side of the smiley face and the screen. The right side of the smiley face is found using its ‘x’ position plus it’s width.
The right side of the screen is setup by default to 800. If it is beyond the right side, we set it to that edge, and set the speed reverse and half, so that it appears to bounce.

Line 142-151: Here we do the same thing as the previous two blocks, but checking to see if it is going above the top of the screen, or below the bottom of the screen.

Line 153: To emulate gravity, every frame we will add ‘2’ to the speed in the y direction, to increase it’s speed down. This makes it so that it will attemp to “fall down”, unless controlled not to.

Line 154: To make some “friction” along the ground, we’ll multiple it by ‘.95’, to slightly brign it down each frame. This will make it appear as if the smiley face slows down over time.

Tutorial Demo

This is what this will look like when you compile:
(click the flash window first, then use the arrow keys to move the smiley face around on screen)

Conclusion

In this section you learned some required function built into flash. There are many more that you can find looking at the “Live docs” on Actionscript 3.0 on ‘Adobe Live Docs’, but this should be enough to get you going.
You should now be able to use the mouse to control things in your games, as well as move using the arrow keys, or any other key for that matter

Where to go from here?

You should now be able to start creating your own games. You will still need to look up stuff, and solve problems, but you should have the basics for creating a game.
I would reccomend looking into the other tutorial series on this site, including the asteroids tutorial. Start coming up with easy game concepts at first, and create more and more complex games each time!

Other Articles in this Series

Bookmark the permalink.

7 Comments

  1. This tutorial series was extremely helpful! Thank you for making it. I’m excited try your Asteroids tutorial series now.

  2. Thanks for making this tutorial. I noticed in line 124 and 125 that you have “smiley_speed.y -= 5;” instead of “smiley_speed.y += 5;” so when you push down, the smiley face goes up.

  3. Thanks for this great series of tutorials!
    I have always wanted to learn to program and have tried learning with some books and other sites. But I never really understood how it all comes together until I found this site. You are really a great teacher.

    Thanks again!

    • Thanks for the feedback, glad it helped you!

      I had a lot of trouble at first too, and was amazed at first when my programming teacher could look at 100 lines of code and see the problem in 10seconds!

      Let me know if there is anything else you’d be interested in, and I’ll try to write another tutorial series on it.
      (although have to finish up my box2d game article, and a few others 😉 )

  4. Thanx a lottt………..!!!!!!!!!!!
    I wish U provided tutorials on intermediate and advanced Topics also…..

Leave a Reply

Your email address will not be published. Required fields are marked *