Well if we are going to discuss character movement… one of the most important has got to be 360 movement based on rotation. I don’t know if there’s a special name for it, I’ve heard it called everything from 360 degree movement, rotational movement, directional movement, to asteroid style movement. Anyway you want to look at it, it’s a movement style that dates back to arcade games and is definitely a usable option in today’s flash game industry. So how hard is making this angle based movement going to be? Not hard at all.
You are reading AS3 Character Movement Read more from this series of articles.
- AS3 Character Movement: Helicopter Games
- AS3 Character Movement: Follow the Mouse Controls
- AS3 Character Movement: Following Mouse with Easing
- AS3 Character Movement: Asteroids Style 360 Degree Movement
In most tutorials on this site we start with a blank slate or a very limited one and work our way up. This time, due to the simplicity of this tutorial I’m just going to give you the source code from the start.
Download the the source code here: AS3 Character Movement: Asteroids Style 360 Degree Movement Final Zip Archive
Here’s what our finished tutorial will look like:
Sweet huh? Let’s get started.
Step 1: Examining the Zip Archive
The contents of the zip are simple. Directionmovement.fla and Ship.as. The fla has two MovieClips, our ship and a shadow MovieClip for our ship. Our ship MovieClip is linked to com.asgamer.directionalmovement.Ship. (If you don’t understand linkage, you should check out the AS3 Flash Games for Beginners series)
Now, there’s something different about this FLA than most on AS Gamer. There is no document class. If you look at the stage in the FLA file you’ll notice the ship is already placed. Because it is already placed on the stage, we don’t have to write a document class to place it. All the code that is linked to our ship will automatically run when the fla is compiled into a swf. Now I wouldn’t make a game this way but for testing and experimenting like we are doing now, it’s perfect.
Next look at our ship MovieClip, you’ll notice it faces towards the right. This is because in flash the 0 rotation starts facing right, 90 faces down, 180 faces left, and 270 faces up (clock-wise). So when we use our geometry functions in Flash (Math.cos, Math.sin, Math.tan2) our results will be based on facing right being the 0 rotation.
Step 2: How we make Rotational Movement.
There’s not a lot to say to preface this step. Just look at the code in Ship.as and I’ll break it down afterwards.
package com.asgamer.directionalmovement { import flash.display.MovieClip; import flash.display.Stage; import flash.events.Event; import com.senocular.utils.KeyObject; import flash.ui.Keyboard; public class Ship extends MovieClip { private var key:KeyObject; private var speed:Number = 0.3; private var rotateSpeed:Number = 5; private var vx:Number = 0; private var vy:Number = 0; private var friction:Number = 0.95; public function Ship () : void { key = new KeyObject(stage); addEventListener(Event.ENTER_FRAME, loop, false, 0, true); } public function loop(e:Event) : void { if (key.isDown(Keyboard.UP)) { vy += Math.sin(degreesToRadians(rotation)) * speed; vx += Math.cos(degreesToRadians(rotation)) * speed; } else { vy *= friction; vx *= friction; } if (key.isDown(Keyboard.RIGHT)) rotation += rotateSpeed; else if (key.isDown(Keyboard.LEFT)) rotation -= rotateSpeed; y += vy; x += vx; if (x > stage.stageWidth) x = 0; else if (x < 0) x = stage.stageWidth; if (y > stage.stageHeight) y = 0; else if (y < 0) y = stage.stageHeight; } public function degreesToRadians(degrees:Number) : Number { return degrees * Math.PI / 180; } } }
Okay. Breakdown.
- imports. The same imports we’ve used at AS Gamer many times before. Nothing special here we just need them so we can access the classes.
- class vars.
key:KeyObject – instance of Senocular’s KeyObject class that we use for checking Key presses
speed:Number - the speed our ship increases (when we press UP, as we’ll setup later)
rotateSpeed:Number – the amount of rotation that occurs (when we press LEFT or RIGHT keys)
vx and vy – the velocity of our ship in x and y
friction - causes our ship to gradually stop - Constructor Function – in our constructor we setup our key object, which needs to stage passed to it and then we setup and ENTER_FRAME event listener so on every frame we can run the loop function
- key = new KeyObject(stage); If you’ve kept up with the tutorials on AS Gamer you’ll remember that you can’t fully access the stage in a class outside the document class. In this case we can because our ship is on the stage when the game starts.
- key.isDown(Keyboard.UP). We simply call isDown in our key class and pass the Keyboard key into the function to see if the key is being pressed. It’s just like AS2.
- vy += Math.sin(degreesToRadians(rotation)) * speed; – The bread and butter of this script. When UP has been pressed we need to adjust our y velocity based on the direction of our ship. If our rotation is 0 or 180 Math.sin will return 0 so our vy isn’t effected. But if our rotation is 90 or 270 it will return 1 or -1 and therefore fully effected. We do the same with our vx value (except with cosine) to get our results in x.
- vy *= friction. If UP isn’t being pressed we apply friction to our vy and vx.
- Then we check if RIGHT or LEFT is being pressed and apply rotation if so.
- y += vy. Let’s apply our velocity.
- x > stage.stageWidth. This section just checks if x is off the screen and resets the x to the other side. It does the same for y.
- degreesToRadians. Last we create our degrees to radians function to convert between the two. Math.sin and Math.cos need a radian value instead of degree to work. So we write this function to do the simple conversion then return us the radian value.
Wow simple huh? Now anytime you move something based on it’s rotation, you know how to do it. If we wanted to make an asteroids game, our ship is almost completely finished. All we’d have to do now is add some asteroids and bullets and we’d be pretty much finished. But this tutorial is about movement… There’s other tutorials on this site that will help you with making the bullets and asteroids.
Alright, that’s all for this tutorial, here’s our SWF once again.
And the final source, AS3 Character Movement: Asteroids Style 360 Degree Movement Final Zip Archive
Similar Posts:
- AS3 Flash Games for Beginners: More Advanced Character Movement
- Asteroids Style Movement… Now with Firing Lasers
- AS3 Character Movement: Helicopter Games
- AS3 Character Movement: Following Mouse with Easing
- AS3 Flash Games for Beginners: Character Movement / Handling Multiple Keypresses









we got your script but it doens’t work for me.
it don’t gave any error’s…
is it because i use more that 1 frame??
can you help me?
thank you
Niels,
I just downloaded the script as it is on the website and tested it. Everything works fine. What do you mean you used more than one frame?
Par,
We made a own game with it.
But it dont work than even we dont get any errors with it.
And we use more frame’s in the flash game.
instead of one frame for the ship, we do a spaceship in more than 1 frame.
niels, your best bet is to go sign up in the forums and post your code so we can help you figure it out. It could be that you don’t have your linkage setup correctly on your movieclips though… but I’m not sure.
FANTASTIC!
Not that I’m totally impressed, but this is a lot more than I expected for when I stumpled upon a link on Digg telling that the info here is awesome. Thanks.
Nice man.
You can put the gravity too. Its more realistic
Great tutorial. cheers
Sorry, I’m really new to as3 lol, but what would the best method of going about this be?:
Making the ship rotate like normal, but moving a larget background MC in the opposite directions again for a large scale map style game?
would just need an example of the movement snippet for bg mc.
Good starting point, but this lacks any sort of maximum speed, so if you hold down thrust you get going insanely fast really quickly. To make a game out of it you need to have some sort of speed limit, like this:
// enforce speed limit – find length of vector
// and scale down to maxSpeed if necessary
var currentSpeed:Number = Math.sqrt((vx * vx) + (vy * vy));
if(currentSpeed > maxSpeed){
vx *= maxSpeed / currentSpeed;
vy *= maxSpeed / currentSpeed;
}
a easier way to set the max speed.
private var speed:Number = 10;
and change
vy += Math.sin(degreesToRadians(rotation)) * speed;
vx += Math.cos(degreesToRadians(rotation)) * speed;
to this
vy = Math.sin(degreesToRadians(rotation)) * speed;
vx = Math.cos(degreesToRadians(rotation)) * speed;
@jaybdemented.
Yes that will work but it will also completely alter the way the ship moves. The sliding effect will no longer work the same way.
Thank you so much for the tutorial, I am very new to AS and is trying to build a asteroid game. You are my life saver to be so kind to post these tutorials.
I have been trying to add the laser to rotate with the ship as well. Should I add the same code to the laser file as well? Right now the laser just shoot straight up and doesn’t rotate. Please give me some advice. Thank you soo much. thank you.
Par..
Still trying to figure out how to face the laser to where the ship is facing. here is the code I am working on, please point me to the right direction…
for the laser:
public class LaserBlue extends MovieClip
{
private var stageRef:Stage;
private var bulletSpeed:Number = 16;
private var xSpeed:Number;
private var ySpeed:Number;
public function LaserBlue (stageRef:Stage, pX:Number, pY:Number, pRotation:Number)
{
this.stageRef = stageRef;
x = pX;
y = pY;
ySpeed= Math.sin(pRotation * Math.PI / 180);
xSpeed= Math.cos(pRotation * Math.PI / 180);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
//move bullet up
x+= xSpeed;
y+= ySpeed;
if (y stage.stageWidth)
x = 0;
else if (x stage.stageHeight)
y = 0;
else if (y < 0)
y = stage.stageHeight;
}
public function degreesToRadians(degrees:Number) : Number
{
return degrees * Math.PI / 180;
}
private function fireBullet() : void
{
//if canFire is true, fire a bullet
//set canFire to false and start our timer
//else do nothing.
if (canFire)
{
stageRef.addChild(new LaserBlue(stageRef, x – 40, y + vy, rotation + vx &&vy));
canFire = false;
fireTimer.start();
}
}
//HANDLERS
private function fireTimerHandler(e:TimerEvent) : void
{
//timer ran, we can fire again.
canFire = true;
}
}
}
Thank you soo soo much for your help. Thank you
Mc :
I see what you’re doing there, and I’m no expert. But I’ve gotten to work with mine and here’s the relevant parts of my BlueLaser.as :
public function Laser (stageRef:Stage, x:Number, y:Number, rotation:Number) : void
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
this.rotation = rotation;
addEventListener (Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
this.x += Math.cos(this.rotation*Math.PI/180)*speed;
this.y += Math.sin(this.rotation*Math.PI/180)*speed;
if (this.x > stageRef.stageWidth)
removeSelf();
if (this.y > stageRef.stageHeight-15)
removeSelf();
}
Use that to get the player to rotate with the mouse:
xd = this.x-stage.mouseX;
yd = this.y-stage.mouseY;
radAngle = Math.atan2(yd, xd);
this.rotation = int(radAngle*360/(Math.PI*2)-90);
Use this for creating the shots:
var shot:Shot = new Shot(stageRef);
stageRef.addChild(shot);
shot.x = this.x;
shot.y = this.y;
shot.rotation = this.rotation;
This for moving them:
x += shotSpeed*Math.sin(rotation*(Math.PI/180));
y -= shotSpeed*Math.cos(rotation*(Math.PI/180));
So I tried this tutorial, and was having the toughest time getting my version to work (Flash CS5 Pro). I kept getting an null object error (stage was set to null). Then I noticed your tutorial file had the Flash Player set to FP 9, not 10. So I changed the player in MY .fla file to use FP9 and it worked.
I’m wondering if you have any knowledge of some error with regards to accessing stage from the document class in FP10?
hey great tutorial
you should create a section about updating the earlier character movement series to use the 360 degree movement
Hi
I really like this tutorial – And I’m trying to make a simple game with it, but the catch is that I want to build the game with Flashbuilder 4 and not Flash Cs5.
*******************************************
Now I have made a “Main class” that will import and Add the class “Player” to the stage.
The class “Player” is basically a (Ship) that imports a MovieClip from flash with linkage.
*******************************************
package
{
import flash.display.Sprite;
import fla10.colosseumGame.Units.Player;
public class ColosseumGame extends Sprite
{
private var _Ship:Player;
public function ColosseumGame()
{
_Ship = new Player();
addChild(_Ship);
_Ship.x = 200;
_Ship.y = 100;
}
}
}
*******************************************
package fla10.colosseumGame.Units
{
import com.senocular.utils.KeyObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.ui.Keyboard;
import flash.display.Stage;
public class Player extends Sprite
{
private var _player:Expo_PlayerUnit;
private var _key:KeyObject;
private var _speed:Number = 0.3;
private var _rotateSpeed:Number = 5;
private var _vx:Number = 0;
private var _vy:Number = 0;
private var _friction:Number = 0.95;
public function Player()
{
_player = new Expo_PlayerUnit();
this.addChild(_player);
_key = new KeyObject(stage);
_player.addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(evt:Event):void
{
if(_key.isDown(Keyboard.UP))
{
_vx += Math.sin(degreesToRadians(rotation)) * _speed;
_vy += Math.sin(degreesToRadians(rotation)) * _speed;
}
else
{
_vx *= _friction;
_vy *= _friction;
}
if(_key.isDown(Keyboard.RIGHT))
rotation += _rotateSpeed;
else if(_key.isDown(Keyboard.LEFT))
rotation -= _rotateSpeed;
x += _vx;
y += _vy;
if(x > stage.stageWidth)
x = 0;
else if(x stage.stageHeight)
y = 0;
else if(y < 0)
y = stage.stageHeight;
}
public function degreesToRadians(degrees:Number):Number
{
return degrees * Math.PI / 180;
}
}
}
*******************************************
Now I don’t get any errors but nothing appears on the stage…
Please help me with this.
Thanks
hi, when i try to move my object up it move right, my object starting position is facing up the screen.the player is a snow border and he has to avoid trees. my code is below:
package src
{
import flash.display.MovieClip;
import flash.events.*;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextField;
public class DocumentClass extends MovieClip
{
public var mutiple:Array;
public var tree:Tree;
public var gameTimer:Timer;
// Assign 4 booleans for the 4 arrow keys
public var keypressUp = false;
public var keypressDown = false;
public var keypressLeft = false;
public var keypressRight = false
public var speed:Number = 0.3;
public var rotateSpeed:Number = 5;
public var vx:Number = 0;
public var vy:Number = 0;
public var friction:Number = 0.95;
public function DocumentClass()
{
mutiple = new Array();
var newTree = new Tree( 100, -15 );
mutiple.push( newTree );
addChild( newTree );
addEventListener(Event.ADDED_TO_STAGE,
init);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, update );
gameTimer.start();
}
public function init(event:Event):void
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
}
public function onKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == 38)
{
keypressUp = true;
}
else if (e.keyCode == 40)
{
keypressDown = true;
}
else if (e.keyCode == 37)
{
keypressLeft = true;
}
else if (e.keyCode == 39)
{
keypressRight = true;
}
}
public function onKeyUp(e:KeyboardEvent)
{
if (e.keyCode == 38)
{
keypressUp = false;
}
else if (e.keyCode == 40)
{
keypressDown = false;
}
else if (e.keyCode == 37)
{
keypressLeft = false;
}
else if (e.keyCode == 39)
{
keypressRight = false;
}
}
public function loop(e:Event) : void
{
if (keypressUp)
{
vy += Math.sin(degreesToRadians(rotation)) * speed;
vx += Math.cos(degreesToRadians(rotation)) * speed;
}
else
{
vy *= friction;
vx *= friction;
}
if (keypressDown)
{
}
if (keypressLeft)
{
// rotate the object
player.rotation -= rotateSpeed;
}
if (keypressRight)
{
// rotate the object
player.rotation += rotateSpeed;
}
player.y += vy;
player.x += vx;
if (player.x > stage.stageWidth)
player.x = 0;
else if (player.x stage.stageHeight)
player.y = 0;
else if (player.y < 0)
player.y = stage.stageHeight;
}
public function update( timerEvent:TimerEvent ):void
{
if ( Math.random() < 0.1 )
{
var randomX:Number = Math.random() * 800;
var newTree = new Tree( randomX, -15 );
mutiple.push( newTree );
addChild( newTree );
}
for each ( var tree:Tree in mutiple )
{
tree.moveDownEverySecond();
if ( player.hitTestObject( tree ) )
{
gameTimer.stop();
}
}
}
public function degreesToRadians(degrees:Number) : Number
{
return degrees * Math.PI / 180;
}
}
}
any help will be appreciated
very nice, but iam developing game with center charecter and bullets, can anybody advice me where i can get good tutorials
regards,
maria suzen.
looked a while for this thank you!
Hey I know this an old article, but it was really helpful for my game: I had been putting the angle calculation in the position sections, not the velocity portion. Thanks a lot!