08-20-2012, 03:07 AM
|
#1
|
|
Registered User
Join Date: Apr 2012
Posts: 9
|
How to get smoother movement.
So right now I am going to try to teach myself AS3 by slowly building up a game. Right now I am starting with keyboard movement. Here is my code:
Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Player;
public var gameTimer:Timer;
public var xSpeed:Number;
public var ySpeed:Number;
public function MultiplayerGame()
{
player=new Player();
addChild( player );
gameTimer= new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
gameTimer.start();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.RIGHT)
{
xSpeed=5;
}
else if (event.keyCode == Keyboard.LEFT)
{
xSpeed=-5;
}
if (event.keyCode == Keyboard.UP)
{
ySpeed=-5;
}
else if (event.keyCode == Keyboard.DOWN)
{
ySpeed=5;
}
}
public function MyKeyUp(event:KeyboardEvent):void
{
ySpeed=0;
xSpeed=0;
}
public function PlayerMovement(timerEvent:TimerEvent):void
{
player.x+=xSpeed;
player.y+=ySpeed;
}
}
}
Very basic stuff. My problem is that it is not very smooth. It stops, and glitches a lot. So my question is how could I make this smoother.
|
|
|
08-20-2012, 04:08 AM
|
#2
|
|
Senior Member
Join Date: Dec 2011
Location: Tucson, AZ
Posts: 1,898
|
Try forcing a screen update in Timer event handler.
event.updateAfterEvent();
ActionScript Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Player;
public var gameTimer:Timer;
public var xSpeed:Number;
public var ySpeed:Number;
public function MultiplayerGame()
{
player = new Player();
addChild( player );
gameTimer= new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.RIGHT)
{
xSpeed=5;
}
else if (event.keyCode == Keyboard.LEFT)
{
xSpeed=-5;
}
if (event.keyCode == Keyboard.UP)
{
ySpeed=-5;
}
else if (event.keyCode == Keyboard.DOWN)
{
ySpeed=5;
}
gameTimer.start();
}
public function MyKeyUp(event:KeyboardEvent):void
{
ySpeed=0;
xSpeed=0;
gameTimer.stop();
}
public function PlayerMovement(event:TimerEvent):void
{
player.x+=xSpeed;
player.y+=ySpeed;
event.updateAfterEvent();
}
}
}
BTW, event arguments can be almost anything; they do not have to correlate with the Event type.
ie: "e", "evt", "event", "rubberDucky", whatever. It's just a local variable that captures information from the Event.
Many advanced AS3 devs just use "e" for ALL Event arguments.
It's quick and consistent.
For code-driven animations, it's a good idea to set the stage framerate in your code, rather than in the IDE.
Probably not a bad idea to set your timer frequency at 60hz, since this is a common display refresh rate.
ActionScript Code:
stage.frameRate = 30;
var timerFrequency:Number = 1000/60;// timer fires at 60hz (16.666ms between calls)
var timer:Timer = new Timer(timerFrequency);
Last edited by [afz]snickelfitz; 08-20-2012 at 04:16 AM.
|
|
|
08-20-2012, 10:10 PM
|
#3
|
|
Registered User
Join Date: Apr 2012
Posts: 9
|
I never knew that about event arguments. That will make everything a lot more convenient. I am still having a problem with the glitching though. It is especially bad when I switch from left to right.
Here is my new code:
Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Player;
public var gameTimer:Timer;
public var xSpeed:Number;
public var ySpeed:Number;
public function MultiplayerGame()
{
player=new Player();
addChild( player );
gameTimer= new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.RIGHT)
{
xSpeed=5;
}
else if (e.keyCode == Keyboard.LEFT)
{
xSpeed=-5;
}
if (e.keyCode == Keyboard.UP)
{
ySpeed=-5;
}
else if (e.keyCode == Keyboard.DOWN)
{
ySpeed=5;
}
gameTimer.start();
}
public function MyKeyUp(e:KeyboardEvent):void
{
ySpeed=0;
xSpeed=0;
gameTimer.stop();
}
public function PlayerMovement(rubberDucky:TimerEvent):void
{
player.x+=xSpeed;
player.y+=ySpeed;
rubberDucky.updateAfterEvent();
}
}
}
After reading my code I think it has something to do with the fact that left, and right speed is all apart of one variable. Let me check.
|
|
|
08-20-2012, 10:25 PM
|
#4
|
|
tadster
Join Date: Feb 2009
Location: Texas
Posts: 2,106
|
Try this and see if it is any better:
ActionScript Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Player;
public var gameTimer:Timer;
public var xSpeed:Number;
public var ySpeed:Number;
private var tStart:Boolean;
private var time:uint;
private var newTime:uint;
private var elapsedTime:uint = 1;
public function MultiplayerGame()
{
player=new Player();
addChild( player );
gameTimer= new Timer(16.66);//<-- this is important.
//1000/60 = 16.66 and 1000/25 = 40, if the frame rate is 25 use 40.
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.RIGHT)
{
xSpeed=5;
}
else if (e.keyCode == Keyboard.LEFT)
{
xSpeed=-5;
}
if (e.keyCode == Keyboard.UP)
{
ySpeed=-5;
}
else if (e.keyCode == Keyboard.DOWN)
{
ySpeed=5;
}
gameTimer.start();
}
public function MyKeyUp(e:KeyboardEvent):void
{
ySpeed=0;
xSpeed=0;
gameTimer.stop();
}
public function PlayerMovement(rubberDucky:TimerEvent):void
{
if(!tStart) { tStart = true; time = getTimer(); }
newTime = getTimer();
elapsedTime = newTime - time;
time = newTime;
player.x+=xSpeed * elapsedTime;
player.y+=ySpeed * elapsedTime;
rubberDucky.updateAfterEvent();
}
}
}
__________________
www.actiontad.com - ActionScript and JavaScript sitting in a tree...
Last edited by tadster; 08-20-2012 at 10:27 PM.
Reason: added tStart property
|
|
|
08-20-2012, 11:25 PM
|
#5
|
|
Registered User
Join Date: Apr 2012
Posts: 9
|
I tried that, and it just kinda spazzed across the stage. Also what does uint mean? I have never seen that before.
Anyway, I have managed to get some smooth movement by adding some Booleans, and such. Here is the new code:
Code:
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Player;
public var gameTimer:Timer;
public var left:Boolean;
public var right:Boolean;
public var up:Boolean;
public var down:Boolean;
public var leftSpeed:Number=5;
public var rightSpeed:Number=5;
public var upSpeed:Number=5;
public var downSpeed:Number=5;
public function MultiplayerGame()
{
player=new Player();
addChild( player );
gameTimer= new Timer (25);
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
gameTimer.start();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.RIGHT)
{
right=true;
}
else if (e.keyCode == Keyboard.LEFT)
{
left=true;
}
if (e.keyCode == Keyboard.UP)
{
up=true;
}
else if (e.keyCode == Keyboard.DOWN)
{
down=true;
}
}
public function MyKeyUp(e:KeyboardEvent):void
{
if (e.keyCode == Keyboard.RIGHT)
{
right=false;
}
else if (e.keyCode == Keyboard.LEFT)
{
left=false;
}
if (e.keyCode == Keyboard.UP)
{
up=false;
}
else if (e.keyCode == Keyboard.DOWN)
{
down=false;
}
}
public function PlayerMovement(rubberDucky:TimerEvent):void
{
if (left)
{
player.x-=leftSpeed;
}
else if (right)
{
player.x+=rightSpeed;
}
if (up)
{
player.y-=upSpeed;
}
else if(down)
{
player.y=downSpeed;
}
rubberDucky.updateAfterEvent();
}
}
}
Anyway to improve this to make it better?
|
|
|
08-20-2012, 11:37 PM
|
#6
|
|
Senior Member
Join Date: Dec 2011
Location: Tucson, AZ
Posts: 1,898
|
Be sure you do not judge animation smoothness in the debug player; use the standalone player to evaluate things like this.
|
|
|
08-20-2012, 11:54 PM
|
#7
|
|
tadster
Join Date: Feb 2009
Location: Texas
Posts: 2,106
|
Yes, that's very true, debug player will be more choppy.
You also have a slight mistake. You only need to ever start the timer once, and it can keep running forever until the game is finished.
Here, I tested this, it's pretty smooth.
I've gone ahead and also showed you how to get the player to move diagonal.
ActionScript Code:
package
{
import flash.display.MovieClip;
import flash.display.Shape;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.events.TimerEvent;
import flash.ui.Mouse;
import flash.media.SoundChannel;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public dynamic class MultiplayerGame extends MovieClip
{
public var player:Shape;
public var gameTimer:Timer;
public var xSpeed:Number = 0;
public var ySpeed:Number = 0;
private var tStart:Boolean;
private var time:Number;
private var newTime:Number;
private var elapsedTime:Number = 1;
private var keys:Object = { 37:0, 38:0, 39:0, 40:0 };
public function MultiplayerGame()
{
player = new Shape();
player.graphics.beginFill(0xFF0000);
player.graphics.drawCircle(0, 0, 25);
addChild( player );
gameTimer= new Timer(33.3);//<-- this is important.
//1000/60 = 16.66 and 1000/25 = 40, if the frame rate is 25 use 40. 1000/30 = 33.33
gameTimer.addEventListener(TimerEvent.TIMER, PlayerMovement);
gameTimer.start();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, MyKeyUp);
}
public function myKeyDown(e:KeyboardEvent):void
{
keys[e.keyCode] = 1;
}
public function MyKeyUp(e:KeyboardEvent):void
{
keys[e.keyCode] = 0;
}
public function PlayerMovement(rubberDucky:TimerEvent):void
{
if(!tStart) { tStart = true; time = getTimer(); }
newTime = getTimer();
elapsedTime = newTime - time;
time = newTime;
xSpeed = 0;
if (keys[37]) xSpeed = -5;
if (keys[39]) xSpeed = 5;
ySpeed = 0;
if (keys[38]) ySpeed = -5;
if (keys[40]) ySpeed = 5;
player.x += xSpeed * (elapsedTime / 64);//play with the 64 Number
player.y += ySpeed * (elapsedTime / 64);
rubberDucky.updateAfterEvent();
}
}
}
Edit: Also, when played in a web browser smoothness also increases.
__________________
www.actiontad.com - ActionScript and JavaScript sitting in a tree...
|
|
|
08-21-2012, 01:33 AM
|
#8
|
|
Registered User
Join Date: Apr 2012
Posts: 9
|
This little bit confuses me syntax wise.
Code:
if(!tStart) { tStart = true; time = getTimer(); }
newTime = getTimer();
elapsedTime = newTime - time;
time = newTime;
xSpeed = 0;
if (keys[37]) xSpeed = -5;
if (keys[39]) xSpeed = 5;
ySpeed = 0;
if (keys[38]) ySpeed = -5;
if (keys[40]) ySpeed = 5;
player.x += xSpeed * (elapsedTime / 64);//play with the 64 Number
player.y += ySpeed * (elapsedTime / 64);
I am assuming that keys[37] is just a more compact way of saying the left arrow key? Earlier in myKeyUp, and myKeyDown you said keyCode. What is keyCode?
Also I why would you divide elapsed time by 64?
|
|
|
08-21-2012, 02:57 AM
|
#9
|
|
tadster
Join Date: Feb 2009
Location: Texas
Posts: 2,106
|
is asking if the property named 37 in the keys Object is true or not null.
The keys Object is pre-populated with properties that correspond to each key that we want to check for. 0 and 1 can also be used like true and false, 0 resolves to false, anything greater than 0 resolves as true.
37 is left, 38 is up, 39 is right, and 40 is down.
Keyboard.RIGHT == 39, and so forth. Those are just constants that help not to have to remember the numbers.
keyCode is the number code of whatever key was pressed, it's given to us by the KeyboardEvent.
I chose 64 because it is a multiple of 2, it could be any number you want, I've found that 64, 96 and 128 work best. It's just there to slow things down.
__________________
www.actiontad.com - ActionScript and JavaScript sitting in a tree...
|
|
|
| Thread Tools |
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT. The time now is 02:21 AM.
///
|
|