Sunday, July 25, 2010

Smooth character movement using AS3

In this Actionscript 3 tutorial we will find out how to move a character with keys smoothly!

Alright, here is the normal movement using arrow keys.



This movement was described in one of my earlier tutorials about keyboard events. Here's the code I'm using for the example above (mc is the hero on stage):

var isRight:Boolean=false
var isLeft:Boolean=false
var isUp:Boolean=false
var isDown:Boolean=false


stage.addEventListener(KeyboardEvent.KEY_DOWN, downKey);
function downKey(event:KeyboardEvent){
 if(event.keyCode==39){
 isRight=true}
 if(event.keyCode==37){
 isLeft=true}
 if(event.keyCode==38){
 isUp=true}
 if(event.keyCode==40){
 isDown=true}
}
 
stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
function upKey(event:KeyboardEvent){
 if(event.keyCode==39){
 isRight=false}
 if(event.keyCode==37){
 isLeft=false}
 if(event.keyCode==38){
 isUp=false}
 if(event.keyCode==40){
 isDown=false}
}

stage.addEventListener(Event.ENTER_FRAME, loop);
function loop(Event){
 if(isRight==true && mc.x<450){mc.x+=5}
 if(isLeft==true && mc.x>50){mc.x-=5}
 if(isUp==true && mc.y>50){mc.y-=5}
 if(isDown==true && mc.y<350){mc.y+=5}
 }


Now take a look at this example:

 

As you can see, the movement is more smooth, there is acceleration and the object doesn't immediately stop when you release a key.

To do this, we have to create a few more variables:

xspeed and yspeed, the variables that represent speed on two axises. When you hold right key, xspeed increases, making the object accelerate, and so on.
maxspeed - the maximum speed our character can move with.
slowdown - the value that slows down our character.

Here's the full commented code:

var isRight:Boolean=false
var isLeft:Boolean=false
var isUp:Boolean=false
var isDown:Boolean=false
var xspeed:Number=0
var yspeed:Number=0
var maxspeed:Number=8
var accel:Number=0.5

stage.addEventListener(KeyboardEvent.KEY_DOWN, downKey);
function downKey(event:KeyboardEvent){
 if(event.keyCode==39){
 isRight=true}
 if(event.keyCode==37){
 isLeft=true}
 if(event.keyCode==38){
 isUp=true}
 if(event.keyCode==40){
 isDown=true}
}
 
stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
function upKey(event:KeyboardEvent){
 if(event.keyCode==39){
 isRight=false}
 if(event.keyCode==37){
 isLeft=false}
 if(event.keyCode==38){
 isUp=false}
 if(event.keyCode==40){
 isDown=false}
}

stage.addEventListener(Event.ENTER_FRAME, loop);
function loop(Event){
// if right is pressed and speed didnt hit the limit, increase speed
if(isRight==true && xspeed<maxspeed){xspeed+=2}
// if left is pressed and speed didnt hit the limit, increase speed (the other way)
if(isLeft==true && xspeed>-maxspeed){xspeed-=2}
// if speed is more than 0, decrease
if(xspeed>0){xspeed-=accel}
// if speed is less than 0, increase
if(xspeed<0){xspeed+=accel}

// just like x, but with y
if(isDown==true && yspeed<maxspeed){yspeed+=2}
if(isUp==true && yspeed>-maxspeed){yspeed-=2}
if(yspeed>0){yspeed-=accel}
if(yspeed<0){yspeed+=accel}

// apply speed to movieclip
mc.x+=xspeed
mc.y+=yspeed

// managing the walls
if(mc.x<30 && xspeed<0){mc.x=30}
if(mc.x>470 && xspeed>0){mc.x=470}
if(mc.y<30 && yspeed<0){mc.y=30}
if(mc.y>370 && yspeed>0){mc.y=370}

}


Thanks for reading!

Related:

Actionscript 3 keyboard event

17 comments:

Vasu said...

great post. u r all tuts are good. thanks dude

Jeremy said...

Thanks for the tut.
Just wondering what this line actually does

stage.addEventListener(KeyboardEvent.KEY_UP, upKey);
function upKey(event:KeyboardEvent){
...
}

Does it simply listen for *ALL* keys that are up? Isn't this sort of listening for much more info than is needed?
I'm just a beginner, I don't really know anything about Flash.

Kirill Poletaev said...

Yes, Jeremy, the code adds a listener for Keyboard when a key is up and it applies to all the keys on your keyboard.

Then, later, in our upKey function, we just check whether a specific key is pressed (for example, right arrow key with the keycode of 39) and commence an action we want.

It is the only way to check if a specific key is up, I'm afraid. But, there's nothing to worry about - AS3 is very efficient and things like this usually won't slow down your performance at all.

Anonymous said...

With flash 8, I keep getting that it doesn't recognize
'keyboard event'

Kirill Poletaev said...

Flash 8 doesn't support Actionscript 3

DITAGIRI said...

Oh great! I love your concept! Thanks a lot!

Norton said...

Sorry but when I try to copy / paste the code, only the keys upward and down work, however inverted :\

What did make wrong?

Kirill Poletaev said...

Sorry, there was a problem displaying the code. It should work now.

Anonymous said...

I think i did exactly what you did but it does not work for me:(
Could someone help me out?

code:


package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.ui.Mouse;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Keyboard;
import flash.display.DisplayObject;
import flash.events.*;

public class project3 extends MovieClip
{
var omhoog:Boolean = false;
var rechts:Boolean = false;
var omlaag:Boolean = false;
var links:Boolean = false;
var speler:avatar = new avatar;

public function project3()
{
var speler:avatar = new avatar;
addChild(speler);

speler.x = 275;
speler.y = 200;

stage.addEventListener(KeyboardEvent.KEY_DOWN, klik);
stage.addEventListener(KeyboardEvent.KEY_UP, los);
stage.addEventListener(Event.ENTER_FRAME, bewegen);
}
private function klik(evt:KeyboardEvent):void
{
if(evt.keyCode == 38)
{
omhoog = true;
speler.y-=5;
trace(speler);

}
if(evt.keyCode == 39)
{
rechts = true;
}
if(evt.keyCode == 40)
{
omlaag = true;
}
if(evt.keyCode == 37)
{
links = true;
}
}

function los(evt:KeyboardEvent)
{
if(evt.keyCode == 38)
{
omhoog = false;
}
if(evt.keyCode == 39)
{
rechts = false;
}
if(evt.keyCode == 40)
{
omlaag = false;
}
if(evt.keyCode == 37)
{
links = false;
}
}

function bewegen(Event)
{
if(rechts==true && speler.x<550){speler.x+=5}
if(links==true && speler.x>50){speler.x-=5}
if(omhoog==true && speler.y>50){speler.y-=5}
if(omlaag==true && speler.y<350){speler.y+=5}
}


}

}

Anonymous said...

Great Tutorial, Simple and Effective tutorial.

Joe said...

Thanks a bunch for this post. I was able to produce a very jerky movement using the keys on my own, but the logic presented here makes sense and works much much better.

My movement is still not quite as smooth as it could be. But, after reading this post I have a much better understanding. Thanks again!!

Anonymous said...

Thanks, helped me a lot.

dontworryaboutitmate said...

Very smooth indeed! Thanks for this!

Anonymous said...

Nice one ! Great Job dude

Mads JF said...

I like it very much! I have one problem though..

My mc stops at the boundary, but the longer I have kept the key down, the longer it takes for the mc to start moving the other way again, when I press the opposite key. Help? :-)

Kirill Poletaev said...

If you use the code provided in this tutorial, you won't have this problem...

Judging by your question, you probably have coordinate values assigned to variables, which are later applied to coordinates of the actual movieclip. If that's true, then you need to change the part of the code that manages the walls, and instead of using movieclip coordinates in the conditionals use your coordinate variables.

If you still have problems, post the code and I'll take a look at it.

hanerzz said...

Hello! Thank you for the this simple code, helped a beginner a lot. But I get errors when I go to another keyframe:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
at proj_fla::MainTimeline/loop()

I don't know what's wrong :( i only used the first code though.

Post a Comment