A lesson in basic movement

Go down

A lesson in basic movement

Post  MitchRichardson on Wed Jul 06, 2011 8:36 am

As I promised, this is the first in a series of small code examples I will be throwing up on this board periodically for programmers who haven't used or learned AS3.0.

Today I'm going over some very basic movement controls implemented with the keyboard. These movement controls would mimic similar movement controls found in games similar to Legend of Zelda: A Link to the Past or any other top down action game.

I have three separate examples showing how to code bad movement, decent but buggy movement, and smooth/functional movement. I will be describing a little bit about how the code works and why things are happening the way they are below the examples. Also if you have any questions your free to sound off in the replies as always. So without further ado...

EXAMPLE 1: BAD MOVEMENT

package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;


public class Tester extends MovieClip
{
public function Tester()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onAddedToStage(event:Event):void
{
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onKeyDown(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.LEFT)
{
this.x -= 5
}
if(event.keyCode == Keyboard.RIGHT)
{
this.x += 5;
}
if(event.keyCode == Keyboard.DOWN)
{
this.y += 5;
}
if(event.keyCode == Keyboard.UP)
{
this.y -= 5;
}

}
public function onRemovedFromStage(event:Event):void
{

this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
this.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}

}

}

This is the worst possible type of movement and you can see why if you test it yourself. Basically what happens is every time you press one of the keyboard arrows, the object moves 5 pixels in that direction. If you hold the button down, after a short delay, it will continuously move in that direction. With this implementation, animation looks choppy and rough, and diagonal movement will not work.

Don't think of every trying to actually use it, or people will laugh at you.

EXAMPLE 2: BEGINNERS FLAWED MOVEMENT



package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;


public class Tester extends MovieClip
{
private var _XSPEED:int = 0;
private var _YSPEED:int = 0;

public function Tester()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onAddedToStage(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onEnterFrame(event:Event):void
{

this.x += _XSPEED;
this.y += _YSPEED;
}
public function onKeyDown(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.LEFT)
{
_XSPEED = -5;
}
if(event.keyCode == Keyboard.RIGHT)
{
_XSPEED = 5;
}
if(event.keyCode == Keyboard.DOWN)
{
_YSPEED = 5;
}
if(event.keyCode == Keyboard.UP)
{
_YSPEED = -5;
}

}
public function onKeyUp(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.LEFT || event.keyCode == Keyboard.RIGHT)
{
_XSPEED = 0;
}

if(event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.UP)
{
_YSPEED = 0;
}
}
public function onRemovedFromStage(event:Event):void
{

this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
this.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
this.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}

}

}

This is how most people who start programming in AS3.0 will make their movement code. As you can see, the movement of the character does not happen in the onKeyDown method anymore. The player now moves according to the onEnterFrame method. This tends to make things look much smoother as the onEnterFrame method runs once every frame, whereas the onKeyDown method only runs every time a key is recognized as pressed.

That means that generally, between 24 - 30 times a second this method will be called, which is a lot more then our keyboard listener. Even when the keyboard key is held down, you generally won't receive more than 10-15 calls of an onKeyDown method.

The way we get the correct direction according to the keypress is by assigning variables to declare the speed and direction of the object. When xspeed and yspeed are 0 (as in when no keys are pressed), that means 0 is constantly being added to the objects directions 30 times a second as shown in the onEnterFrame method, which does nothing. But when a key is pressed , our variables get set to +/- 5, and that gets constantly added or subtracted from the objects coordinates 30 times a second, giving the movement. The new onKeyUp method handles setting the x and y speeds back to zero when you let go of the keys, so the object doesn't continue to move after you let go of the keys.

However, this isn't without it's problems. Certainly it's an improvement over the last example. You gain smooth looking movement, as well as the ability to move diagonally. Sounds perfect right? Wrong. This code creates anomalies that are a tad hard to explain and much easier to see if you try testing this code out itself. I'll try my best to show you here anyways.

Basically, when you press a key down, say left, your xspeed gets set to -5. Great, your now moving left at 5 pixels per frame, or 150 pixels per second. You wish to turn around for a second, so you quickly press the right key. Since you pressed right more recently, it overrides the left key your still pressing, and switches xspeed to 5. Great, now your moving right. Now that you've changed directions quickly, you want to go back to the left. Great, your fingers still on the left key from before, so just let go of your right key and...wait, what? You stopped. This is because the onKeyUp method seen your right key go up, which was more recently pressed then your left, setting xSpeed to 0. Like I said, hard to explain, test it yourself and youll see what I mean. It basically bogs down any game with this movement control as it will limit the movement and feel clunky.

And with those said, last but not least...

EXAMPLE 3: THE BASIC FUNCTIONALLY AND WELL WORKING MOVEMENT CODE



package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;


public class Tester extends MovieClip
{
private var _LEFT:Boolean;
private var _RIGHT:Boolean;
private var _UP:Boolean;
private var _DOWN:Boolean;
private var _SPEED:int = 5;

public function Tester()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onAddedToStage(event:Event):void
{
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onEnterFrame(event:Event):void
{
var XVel:int;
var YVel:int;
if(_LEFT)
{
XVel = -_SPEED;
}else if(_RIGHT)
{
XVel = _SPEED;
}
if(_UP)
{
YVel = -_SPEED;
}else if(_DOWN)
{
YVel = _SPEED;
}

this.x += XVel;
this.y += YVel;
}
public function onKeyDown(event:KeyboardEvent):void
{
trace("Key Pressed");
if(event.keyCode == Keyboard.LEFT)
{
_LEFT = true;
}
if(event.keyCode == Keyboard.RIGHT)
{
_RIGHT = true;
}
if(event.keyCode == Keyboard.DOWN)
{
_DOWN = true;
}
if(event.keyCode == Keyboard.UP)
{
_UP = true;
}

}
public function onKeyUp(event:KeyboardEvent):void
{
if(event.keyCode == Keyboard.LEFT)
{
_LEFT = false;
}
if(event.keyCode == Keyboard.RIGHT)
{
_RIGHT = false;
}
if(event.keyCode == Keyboard.DOWN)
{
_DOWN = false;
}
if(event.keyCode == Keyboard.UP)
{
_UP = false;
}

}
public function onRemovedFromStage(event:Event):void
{

this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
this.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
this.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}

}

}


This one's also a tad hard to explain in detail, but here's the jist of it. Instead of setting our speed in the onKeyDown and onKeyUp methods, we set boolean flags instead. Because the flags are being checked in onEnterFrame(which runs ~30 times a second remember), as soon as one is updated in those methods, they will be seen in the onEnterFrame method and handled accordingly. There isn't a preference over which key is pressed more recently in the onEnterFrame method, it just see's whats happening and acts accordingly. This gives smooth movement that doesn't randomly stop in the middle of some action. Check them out yourself when you have time. And I advise you type them out yourself as opposed to copying them, it helps you learn.

Like I said, any questions just ask below. Most of this was said with the thought in mind that you have background in some coding language. If you want me to go over realllllly basic coding architecture in AS3.0 let me know and I'll consider it.

The next short lesson will be most likely on basic collision detection, the different types AS3.0 supports, and the ways in which they differ.

Cheers


Last edited by MitchRichardson on Wed Jul 06, 2011 3:17 pm; edited 1 time in total
avatar
MitchRichardson
Admin

Posts : 23
Join date : 2011-07-03
Age : 30
Location : Halifax

View user profile

Back to top Go down

Re: A lesson in basic movement

Post  brycehalda on Wed Jul 06, 2011 11:36 am

MitchRichardson wrote:I'll try my best anyways to show you here anyways.
I understood you perfectly.

brycehalda

Posts : 13
Join date : 2011-07-05
Age : 23
Location : Spring Hill, Kansas

View user profile

Back to top Go down

Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum