I've been looking to make an animation using ActionScript 3.0 in Adobe Flash Professional where a character (John) can be moved by the viewer using the arrow keys. I've made two sprites, John (the default standing character) and JohnLeg (the character with a raised leg), and I switch between them when the up key is pressed to make it look like he is walking. I've tried this by making one invisible and the other visible.
However, at the moment it only shows JohnLeg for 0 seconds, so I believe I need to set a time delay when he moves to show JohnLeg for half a second before switching back.
My code only considers the up key at the moment, and most of it was taken using the code snippets in Adobe Flash:
var upPressed:Boolean = false;
John.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey_4);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed_4);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed_4);
function fl_MoveInDirectionOfKey_4(event:Event)
{
JohnLeg.visible = false;
JohnLeg.x = John.x
JohnLeg.y = John.y
if (upPressed)
{
JohnLeg.visible = true;
John.visible = false;
John.y -= 5;
//set time delay here
JohnLeg.visible = false;
John.visible = true;
}
}
function fl_SetKeyPressed_4(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = true;
break;
}
}
function fl_UnsetKeyPressed_4(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = false;
break;
}
You could try setTimeout.
Here it some help doc http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00000602.html
Related
I'm here again for your help :{ I have a question which I tried to google it but can't find the answer. Well,..May be there is an answer but I just can't make it works? I'm in a process of learning AS3 so let's say I'm still new here.
What I'm doing is making a keyboatd to respond with the vdo files I have. It is a very simple idea as press-n-play. Each keys has their vdos to play and if you press another button while the first one is still pressing, it'll play another vdo of its key. I have make this as boolean with function of keydown and keyup like this:
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.net.NetStream;
import flash.net.NetConnection;
import flash.media.Video;
var isLeft:Boolean = false;
var isRight:Boolean = false;
var video;
var nc;
var ns;
stage.addEventListener(KeyboardEvent.KEY_DOWN,onDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onUP);
this.addEventListener(Event.ENTER_FRAME,playVid);
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.client = this;
video = new Video(550,400);
addChild(video);
video.attachNetStream(ns);
function onDown(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37 :
//ns.play(TomAndJerry.flv);
isLeft=true;
break;
case 39 :
//ns.play(westler.flv);
isRight = true;
break;
}
}
function onUP(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case 37 :
isLeft = false;
break;
case 39 :
isRight = false;
break;
}
}
function playVid(e:Event):void
{
if (isLeft)
{
trace(kk);
ns.play(westler.flv);
isLeft = false;
}
else if (isRight)
{
trace(PP);
ns.play(TomAndJerry.flv);
//isRight = false;
}
}
I have tried making a keydown function without using any boolean or those true of false things to just play a vdo. It worked but, I still have the same problem that I can't find a solution which is ....
When you hold down the keyboard button the vdo will keep start at the beginning.
All I want is to play the vdo even the key is press down. If the vdo ends then play again as loop but if the key is up the vdo will play until it ends.
And if there are more than one button are holding down just play the vdo of the lastest pressed button.
T-T"
Thanks.
Ps. I have tried removeEventListener but, it made every buttons' function gone.
your playvid function is called each frame so i think it's normal your video don't start, I think you could try to change your code as follow:
// add net status handler event to check the end of the video
ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
// remove this line
//this.addEventListener(Event.ENTER_FRAME,playVid);
/** a key is pressed **/
function onDown(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
// start the video just if the video don't play
if(!isLeft) ns.play("TomAndJerry.flv");
// video left is playing
isLeft = true;
// video right isn't playing
isRight = false;
break;
case Keyboard.RIGHT:
// start the video just if the video don't play
if(!isRight) ns.play("westler.flv");
// video rightis playing
isRight = true;
// video left isn't playing
isLeft = false;
break;
}
}
/** a key is released **/
function onUP(e:KeyboardEvent):void
{
switch (e.keyCode)
{
case Keyboard.LEFT:
isLeft = false;
break;
case Keyboard.RIGHT:
isRight = false;
break;
}
}
/** net status change, verify if we reach the end of the video **/
function netStatusHandler(e:NetStatusEvent):void
{
// when netStatus code is NetStream.Play.Stop the video is complete
if (e.info.code == "NetStream.Play.Stop")
{
// right key is still pressed we loop the video
if( isRight ) ns.play("westler.flv");
// left key is still pressed we loop the video
else if( isLeft ) ns.play("TomAndJerry.flv");
}
}
I hope this will help you :)
I'm developing a 3D game and I've noticed some odd behaviour when I hold down the movement keys; the game seems to temporarily ignore the mouse position and stops updating which way the player is facing. The game does not freeze - it's just as if it stops paying attention to the position of the mouse.
Here's the code I'm using to get key presses and releases:
public function keyPressed(e:KeyboardEvent):void {
switch (e.keyCode) {
case 32:
_keySpace = true;
break;
case 81:
if (!keyQ) {
keyQ=true;
}
break;
case 69:
if (!keyE) {
keyE=true;
}
break;
case 65:
if (!keyA) {
keyA=true;
}
break;
case 68:
if (!keyD) {
keyD=true;
}
break;
case 87:
if (!keyW) {
keyW=true;
}
break;
case 83:
if (!keyS) {
keyS=true;
}
break;
}
}
public function keyLift(e:KeyboardEvent):void {
if (e.keyCode==32) {
_keySpace = false;
} else if (e.keyCode==81) {
keyQ=false;
} else if (e.keyCode==69) {
keyE=false;
} else if (e.keyCode==65) {
keyA=false;
} else if (e.keyCode==68) {
keyD=false;
} else if (e.keyCode==87) {
keyW=false;
} else if (e.keyCode==83) {
keyS=false;
}
}
And the code to update the mouse position is just an ENTER_FRAME event:
addEventListener(Event.ENTER_FRAME, enterFrame);
...that triggers the main game loop. Here's the relevant part that uses the mouse position. The mouseX and mouseY properties are used in Player to rotate the view left/right and up/down.
private function enterFrame(e:Event=null):void {
_player.update(mouseX, mouseY);
}
All of that works fine - it's just this problem with holding down the strafing keys; it's as if, once the key starts repeating, the game is taking all its time resolving those events and neglects to update the rotation - even though it's not dependent on a MouseEvent.
Does anyone know how to make Flash ignore repeating keys when the key is held down? Or is there some other problem?
Cheers.
You could check when your key handler was last triggered, and if it's more recently than a certain threshold, ignore it. You could make it a tenth of a second:
private static const KEY_THRESHOLD:int = 100; // 100 ms = 1/10 second
private static var lastPressedAt:int;
public function keyPressed(e:KeyboardEvent):void {
var now:int = new Date().getTime();
if (lastPressedAt > 0 && now - lastPressedAt < KEY_THRESHOLD) {
return;
}
lastPressedAt = now;
// etc...
I am currently working on a game where you need to survive as long as possible while dodging questions that come your way. (all with AS3)
At the moment I am going from 1 scene to another in between the game field and the question field, but everytime I go to the question scene the timer in the game scene resets itself. I was wondering if it was possible to have the timer continue while being in the question scene?
Also I have a movable character in between the menus which incidentally are also made in different scenes and the player is able to move him around, and I would very much like him to stay in the last position he was in the next screen, as in I move him to the top right in the main menu and when I go to the options menu I want him to still be in the top right and not in his initial position.
As for my timer this is the code I am using at the moment:
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.globalization.DateTimeFormatter;
var timer:Timer = new Timer(100);
timer.start();
timer.addEventListener(TimerEvent.TIMER, timerTickHandler);
var timerCount:int = 0;
function timerTickHandler(Event:TimerEvent):void
{
timerCount += 100;
toTimeCode(timerCount);
}
function toTimeCode(milliseconds:int) : void {
//create a date object using the elapsed milliseconds
var time:Date = new Date(milliseconds);
//define minutes/seconds/mseconds
var minutes:String = String(time.minutes);
var seconds:String = String(time.seconds);
var miliseconds:String = String(Math.round(time.milliseconds)/100);
//add zero if neccecary, for example: 2:3.5 becomes 02:03.5
minutes = (minutes.length != 2) ? '0'+minutes : minutes;
seconds = (seconds.length != 2) ? '0'+seconds : seconds;
//display elapsed time on in a textfield on stage
timer_txt.text = minutes + ":" + seconds+"." + miliseconds;
}
And my character is using this code:
/* Move with Keyboard Arrows
Allows the specified symbol instance to be moved with the keyboard arrows.
Instructions:
1. To increase or decrease the amount of movement, replace the number 5 below with the number of pixels you want the symbol instance to move with each key press.
Note the number 5 appears four times in the code below.
*/
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
rutte.addEventListener(Event.ENTER_FRAME, fl_MoveInDirectionOfKey);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function fl_MoveInDirectionOfKey(event:Event)
{
if (upPressed)
{
rutte.y -= 5;
}
if (downPressed)
{
rutte.y += 5;
}
if (leftPressed)
{
rutte.x -= 5;
rutte.scaleX = 1; // face left
}
if (rightPressed)
{
rutte.x += 5;
rutte.scaleX = -1; // face right
}
}
function fl_SetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = true;
break;
}
case Keyboard.DOWN:
{
downPressed = true;
break;
}
case Keyboard.LEFT:
{
leftPressed = true;
break;
}
case Keyboard.RIGHT:
{
rightPressed = true;
break;
}
}
}
function fl_UnsetKeyPressed(event:KeyboardEvent):void
{
switch (event.keyCode)
{
case Keyboard.UP:
{
upPressed = false;
break;
}
case Keyboard.DOWN:
{
downPressed = false;
break;
}
case Keyboard.LEFT:
{
leftPressed = false;
break;
}
case Keyboard.RIGHT:
{
rightPressed = false;
break;
}
Thank you in advance for all the help you can give me.
Kind Regards.
in flash there is a fundamental aspect of how timeline and scenes works. Once you move away from a frame to another frame, The content of the frame and it's properties/states/actions are gone and reseted.
Personally I recommend you use a single scene with a timeline divided into frames labeled, there you can specify a layer for the actions and global variables, one for the user interface and another one for the specific actions of each frame. example:
So you never lose the reference of variables because the frame is not constantly recreated, all your important actions, including you timer, should be in your first frame.
I was testing, here you can see a working example: http://db.tt/FZuQVvt3. Here you can download the FLA file to be used as a base for your project: http://db.tt/RHG9G5lo
I've been trying to come up with a simple code that plays a sound "jump" from the library each time the spacebar is pressed, but no luck. Everything I try turns my fla/swf into a strobe light.
var spacebarDown:Boolean = false;
stage.addEventListener(KeyboardEvent.KEY_DOWN, _keyHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, _keyHandler);
function _keyHandler(e:KeyboardEvent):void
{
if(e.keyCode == 32)
{
switch(e.type)
{
case KeyboardEvent.KEY_DOWN:
if(!spacebarDown)
{
spacebarDown = true;
// Play Sound.
var sfx:YourSound = new YourSound();
sfx.play();
}
break;
case KeyboardEvent.KEY_UP: spacebarDown = false; break;
}
}
}
I want to stop the movieclips movement when it hits a wall (another movieclip).
The example below works, but after the collision the movieclip 'blocks' all movement to the left...
My question to you is, is this a good way and why isn't it working well?
There will be something wrong in this code, but i'm learning.
For now the example with the leftArrow key;
variables to check the key, if it's hitting the walls and if it's moving or not:
var leftArrow:Boolean;
var speed:int = 10;
var hitting:Boolean;
var ismoving:Boolean;
event listeners for the keys/movement and detecting collision:
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.ENTER_FRAME, walking);
stage.addEventListener(Event.ENTER_FRAME, detectHit);
detecting collision function:
function detectHit(e:Event) :void
{
if(char.hitTestObject(bounds))
{
hitting = true;
}
}
function to the left arrow key:
function keyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = true;
}
}
function keyReleased(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
leftArrow = false;
}
}
And the reason it's not working is probably here, but I don't understand why not:
function walking(event:Event):void {
if (rightArrow) {
char.x += speed;
}
if (leftArrow && ! hitting) {
char.x -= speed;
}
else
{
ismoving = false
}
if (leftArrow && ! hitting)
char will move if hitting is false. When char.hitTestObject(bounds) is true you are setting hitting to true. You are not setting hitting again to false anywhere. That's why once left wall is hit it stops left movement permanently. You need to figure out suitable condition to set hitting to false again.
Adding an else branch in detectHit should solve the problem.
function detectHit(e:Event):void {
if(char.hitTestObject(bounds))
{
hitting = true;
} else {
hitting = false; // add this
}
}
Allthough Taskinoor's method should work, I would suggest another way to do your hittests.
Since you probably are creating a game (character and bounds), you will have more than one bound. In that case, I would strongly suggest bitmap-hittesting. This way, you can create all your bounds in one movieclip and test for a hit.
I will explain this by using the example of a maze. The maze would then be some lines in a movieclip, randomly put together. If you use HitTestObject and you aren't hitting one of the lines, but your character is over the movieclip, hitTestObject will return true, even though you are not hitting a wall. By using bitmapHitTesting, you can overcome this problem (BitmapHitTest takes transparant pixels into account, whereas hitTestObject does not).
Below you can find an example of how to do bitmapHitTesting. Creating the bitmaps in this function is not necesarry if they do not change shape. In that case, I would suggest placing the code for the bitmapdata in a added_to_stage-method.
private var _previousX:int;
private var _previousY:int;
private var _bmpd:BitmapData ;
private var _physicalBitmapData:BitmapData;
private function walkAround(e:Event):void
{
var _xTo:int = //Calculate x-to-position;
var _yTo:int = //Calculate y-to-position;
//If your character doesn't change shape, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_bmpd = new BitmapData(char.width, char.height, true, 0);
_bmpd.draw(char);
//If your bounds are static, you don't have to recalculate this bitmapData over and over.
//I suggest placing it in a ADDED_TO_STAGE-Event in that case.
_physicalBitmapData = new BitmapData(bounds.width, bounds.height, true, 0);
_bmpd.draw(bounds);
//The below line is the actual hittest
if(_physicalBitmapData.hitTest(new Point(0, 0), 255, _bmpd, new Point(char.x, char.y), 255))
{
char.x = _previousX;
char.y = _previousY;
}
else
{
char.x = _xTo;
char.y = _yTo;
}
_previousX = char.x;
_previousY = char.y;
}
Look at my hint,
function loop(Event)
{
if(isHit==false)
{
if(isRight==true){head_mc.x+=1}
if(isLeft==true){head_mc.x-=1}
if(isUp==true){head_mc.y-=1}
if(isDown==true){head_mc.y+=1}
}
if(head_mc.hitTestObject(build_mc))
{
isHit=true;
if(isRight==true){head_mc.x-=1}
if(isLeft==true){head_mc.x+=1}
if(isUp==true){head_mc.y+=1}
if(isDown==true){head_mc.y-=1}
}
else
{
isHit=false;
}
}
I use step back to opposite direction instead.