Flash GotoFrame on Keypress - actionscript-3

I am trying to figure out some code where when I press one of the 4 arrow keys, flash goes to a certain frame on the timeline. And when none of these keys are being pressed, it will return to its original start point on the timeline. I have seen some examples on this site, but I am struggling with it, especially returning to the original point on the timeline when there are no keypresses.
So for example :
stage.addEventListener(KeyboardEvent.KEY_DOWN, reportKeyDown);
function reportKeyDown(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT)
{
gotoAndStop(40);
}
if (event.keyCode == Keyboard.RIGHT)
{
gotoAndStop(30);
}
if (event.keyCode == Keyboard.UP)
{
gotoAndStop (10);
}
if (event.keyCode == Keyboard.DOWN)
{
gotoAndStop (20);
}
}
stop();
I can get it to go to various points on the timeline, but I do not know how to make it return to its original point on the time line (keyframe 1) when none of those keyboard keys are being pressed.
What I am trying to do is to show on screen when a button is being pressed, and when its no longer being pressed to disapear
If anyone can help, I would be grateful. Thanks

Detect KEY_DOWN and KEY_UP events, if you want to return to the first frame when you release the keys, this could be a possible solution:
var frames:Object = {
38: 10, // Up Key
40: 20, // Down Key
37: 40, // Left Key
39: 30 // Right Key
};
stage.addEventListener(KeyboardEvent.KEY_DOWN, showMessage);
stage.addEventListener(KeyboardEvent.KEY_UP, hideMessage);
function showMessage(event:KeyboardEvent):void{
if(frames.hasOwnProperty(event.keyCode.toString())) gotoAndStop( frames[event.keyCode] );
}
function hideMessage(evt:KeyboardEvent):void{
gotoAndStop( 1 );
}

Related

Need help fixing player jumping diagonally Flash CS4

I can't figure out why when I try and get my player to jump diagonally by pressing the right and up arrow key it does nothing, I've used trace to see if anything was happening and nothing was when they were used together.
Up won't work by itself or with right but when right is by itself it works.
player is named hero, platforms are named platform, platform2, platform3 etc
platforms are in the platform layer
stop();
var gravity:Number=5; //Very important, allows player to fall
var movex:Number=0; // Moving players X
// Moving player
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHero);
var speed=10;
function moveHero(event:KeyboardEvent) {
if (event.keyCode==Keyboard.LEFT) {
hero.x-=speed;
hero.play();
}
if (event.keyCode==Keyboard.RIGHT) {
hero.x+=speed;
hero.play();
}
}
hero.addEventListener(Event.ENTER_FRAME, testCollision2);
// Allowing player to jump when on platform
function testCollision2(e: Event) {
//Allowing player to jump when on platform continued
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHeroUP);
function moveHeroUP(event:KeyboardEvent) {
if (hero.hitTestObject(platform) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform2) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform4) && event.keyCode==Keyboard.UP) {
gravity=-50;
hero.y=hero.y+gravity;
}
if(hero.hitTestObject(platform) && event.keyCode==Keyboard.UP && event.keyCode==Keyboard.RIGHT){
movex = 20;
hero.x = hero.x + movex;
gravity =-50;
hero.y = hero.y + gravity;
}
}
I'm trying to get the player to jump in the code chunk at the very end
Flash CS4
AS3
To start, let's go through how you've set up this code and explain what's happening.
You have this line:
hero.addEventListener(Event.ENTER_FRAME, testCollision2);
Which is saying, every frame tick that hero exists, run the function testCollision2. Frame tick here doesn't relate to timeline frames, it relates to the frame rate of your application. So if that is set to 12, that function will run 12 times every second.
Inside testCollision2, you add another listener:
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveHeroUP);
and create an inline function called moveHeroUP. So every frame tick, you create a new function, and attach it to a key down event. So (assuming 12 frames per second) 5 seconds into your application, you'll have 60 keyboard listeners all doing the same thing. This is also a memory leak (as you keep creating a new function every frame), so eventually your program will crash.
To get to the actual question, a keyboard event is tied to one specific key. This means the event's keyCode is only ever one key (the key that triggered the event). So doing something like (event.keyCode==Keyboard.UP && event.keyCode==Keyboard.RIGHT) will always be false because event.keyCode only ever holds one value.
A common approach to your situation, is to have one global key down and key up listener. Then use a dictionary to store which keys are currently down:
//create just one key down listener
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
//create a dictionary to store key presses
var keyboardDown:Dictionary = new Dictionary();
function keyDownHandler(e:KeyboardEvent):void {
keyboardDown[e.keyCode] = true;
}
function keyUpHandler(e:KeyboardEvent):void {
keyboardDown[e.keyCode] = false;
}
What you're doing here, is when a key down event fires, you set the value in the dictionary to true (with the keycode as the dictionary key), then on the key up event you set it to false.
Now, in your ENTER_FRAME handler, you use the dictionary values to check for key combinations:
hero.addEventListener(Event.ENTER_FRAME, moveHero);
function moveHero(event:Event) {
//DO ALL YOUR MOVEMENTS IN ONE ENTER FRAME FUNCTION
if (keyboardDown[Keyboard.LEFT]) {
hero.x-=speed;
hero.play();
}
if (keyboardDown[Keyboard.RIGHT]) {
hero.x+=speed;
hero.play();
}
if (hero.hitTestObject(platform) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform2) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
} else if (hero.hitTestObject(platform4) && keyboardDown[Keyboard.UP]) {
gravity=-50;
hero.y=hero.y+gravity;
}
if(hero.hitTestObject(platform) && keyboardDown[Keyboard.UP] && keyboardDown[Keyboard.RIGHT]){
movex = 20;
hero.x = hero.x + movex;
gravity =-50;
hero.y = hero.y + gravity;
}
}

Firing bullets on a certain frame.

I could not find topic like this and that is why I am posting this question. I have a side scrolling game with the character set up in positions with frame labels- animation states to stand, jump, run, kneel and fire. She is also made to fire bullets with separate class file. The problem is that right now she is firing bullets in all of the animation states. The question is how do I make this character fire the bullets only on the frame label fire. The frame label fire consists of 2 frames and I want the launching of the bullet to happen on the second frame. Which means that the keyboard space will be pressed for a second or two before it goes to this frame and then it will fire (like in real life).
I tried to connect the animation state to the bullets somehow and tried to put the condition in these lines of code somehow:
if(e.keyCode == Keyboard.SPACE){
if (Animation state "Fire (2)")
fireBullet();
}
But it did not work, it doesn't know what I am talking about. The class file for the bullet is separate and I don't think is relevant to the problem.
The rest of the timeline code is like this:
var bulletList:Array = new Array();
if(e.keyCode == Keyboard.SPACE){
fireBullet();
}
}
function fireBullet():void
{
var playerDirection:String;
if(player.scaleX < 0){
playerDirection = "left";
} else if(player.scaleX > 0){
playerDirection = "right";
}
var bullet:Bullet = new Bullet(player.x - scrollX, player.y - scrollY,
playerDirection xSpeed);
back.addChild(bullet);
Thank you. I hope that my question is clear.
There is addFrameScript, AS3's mystery function that can be useful in this situation. And that would look something like this:
playerAnimation.addFrameScript( insertFrameNumber, fireBullet );
addFrameScript runs the method passed as a parameter when the MovieClip reaches a certain frame.
I believe how you would want to use this in your current code:
player.addFrameScript( 5, fireBullet );
Then in your KEY_UP handler:
function keyUpHandler(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.SPACE){
spacePressed = false;
player.gotoAndPlay("fire");
}
if(e.keyCode == Keyboard.LEFT){
leftPressed = false;
}
else if(e.keyCode == Keyboard.RIGHT){
rightPressed = false;
}
else if(e.keyCode == Keyboard.UP){
upPressed = false;
}
else if(e.keyCode == Keyboard.DOWN){
downPressed = false;
}
}

AS3 Keyboard Controlled Character - Animation problems with multiple key presses

I have a keyboard controlled character in a game which has a stationary frame when no
keys are pressed and four different animations for the up, down, left, right directions
(No diagonal movement).
So when left key is pressed, _character moves left across the screen and the left animation is played. When the key is released/Key up the stationary frame plays where the character is still.
This works fine at a slow pace but when multiple keys are being pressed to maneuver around an obstacle etc, the character often sticks to the stationary position and only plays the animations after a delay. The movement of the Movieclip is fine using velocity, but the animations suffer.
Its something to do with the key up handler surely. I’m a beginner so I’m sure I just can’t get my head around some simple logic, but I can’t figure it out! Help me please. No matter how fast I tap the keys I need that animation to play, and only when nothing is being pressed should I see the stationary image.
Character in its own class, with Velocity variables.
package
{
import flash.display.MovieClip;
import flash.display.DisplayObject
[Embed(source="../swfs/characterRes.swf", symbol="Character")]
public class Character extends MovieClip
{
//Public properties
public var vx:int = 0;
public var vy:int = 0;
public function Character()
{
}
}
}
Keydown and KeyUp listeners added.
_stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
_stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
In enterFrame the characters X and Y position is linked to the velocity
private function enterFrameHandler(event:Event):void
{
//Move the game character and check its stage boundaries
_character.x += _character.vx;
_character.y += _character.vy;
}
The keydown handler uses the arrows and WASD to control the velocity and plays that directions specific frame (with embedded animation)
private function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT || event.keyCode == 65 )
{
_character.vx = -4;
_character.gotoAndStop(4);
}
else if (event.keyCode == Keyboard.RIGHT || event.keyCode == 68)
{
_character.vx = 4;
_character.gotoAndStop(5);
}
else if (event.keyCode == Keyboard.UP || event.keyCode == 87 )
{
_character.vy = -4;
_character.gotoAndStop(2);
}
else if (event.keyCode == Keyboard.DOWN || event.keyCode == 83)
{
_character.vy = 4;
_character.gotoAndStop(3);
}
}
Key up handler stops velocity and plays first frame which is the stationary image.
private function keyUpHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT || event.keyCode == Keyboard.RIGHT
|| event.keyCode == 65 || event.keyCode == 68)
{
_character.vx = 0;
_character.gotoAndStop(1);
}
else if (event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.UP
|| event.keyCode == 87 || event.keyCode == 83 )
{
_character.vy = 0;
_character.gotoAndStop(1);
}
}
I also made the stationary image bright red to make it easier for me to spot and once I start moving the character in different directions I see Red! (literally & figuratively!)
Update
Vesper's answer has solved the animation state problem brilliantly but this new control system seems to want to travel diagonally which sends the character on an unwanted path.
My stage is a grid of 50px squares. Character is 50px and 50px boxess (with collision detection) are around with a 50px border around them so the character can maneuver around the stage.
If I press/hold one direction the character moves no problem (left to right and Up to down is fine too.), but if I go left then down or up then right etc, the character will travel that direction then continue that direction around the boxes. When I tested without the boxes the character continues in that direction diagonally.
So if I want to go clockwise around a box (starting in the bottom left side of it), I'll press up, then right and if I dont press down VERY quickly, the character will travel up and right again, towards the top right of the stage. (Character does stop if key is released.)
So if I press two keys from the opposing updown or leftright variables, it wants to travel diagonally. Any ideas how to solve this?
Final Update
Vesper's answer solved my original animation problem. I'll ask new questions to deal with remaining queries.
You actually have four de-facto independent key states, up key pressed/released, down key, left key, right key. Technically one can implement special actions in case of two opposite keys be pressed at one time, in your case it's not needed but it's still worth mentioning. So, you handle all of them separately, and only then choose where should your character face.
var bDown:Boolean=false;
var bUp:Boolean=false;
var bLeft:Boolean=false;
var bRight:Boolean=false;
// declare vars to store key states. You can use an array if you want
private function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.LEFT || event.keyCode == 65 )
{
bLeft=true;
// now, instead of directly attaching the movement, just set flag
}
else if (event.keyCode == Keyboard.RIGHT || event.keyCode == 68)
{
bRight=true;
}
else if (event.keyCode == Keyboard.UP || event.keyCode == 87 )
{
bUp=true;
}
else if (event.keyCode == Keyboard.DOWN || event.keyCode == 83)
{
bDown=true;
}
}
Same for key up handler, setting values to false. Now doing the parsing of the actual character's movement according to keys pressed. The best place is the enter frame handler - good thing you have it in place already.
private function enterFrameHandler(event:Event):void
{
var updown:Boolean=Boolean(!(bUp==bDown));
// if both are true or both are false, this is false. If this is true,
// we are moving upwards or downwards
var leftright:Boolean=Boolean(!(bLeft==bRight));
// same here
if (!updown && !leftright) {
// not moving anywhere
_character.gotoAndStop(1);
_character.vy=0;
_character.vx=0;
// other mechanics might be in place in case you decide to implement inertia, for example
} else {
if (bUp) {
_character.vy=-4; // hardcoding this might get you issues later
// will still do for today's task
_character.gotoAndStop(2);
} else if (bDown) {
_character.vy=4;
_character.gotoAndStop(3);
}
// one side parsed. Note, with this sequence the leftwards or rightwards
//animation supersedes up/down. But, we don't have diagonals, so there should be superseded animation
if (bLeft) {
_character.vx=-4;
_character.gotoAndStop(4);
} else if (bRight) {
_character.vx=4;
_character.gotoAndStop(5);
}
}
// Okay, now velocity and facing is set, proceed with move
//Move the game character and check its stage boundaries
_character.x += _character.vx;
_character.y += _character.vy;
}

AS3 Animation stop at frame 1

I'm really new at AS3, I used to be coding in AS2, but for more than a year I don't use Flash or ActionScript.
My problem is when I press left or right arrow which is defenied to move the character to right and left the animation just stop at the first frame. The idle animation works fine, but the walk animation starts and stop in frame 1 everytime I press the buttons.
vector.gotoAndPlay("parado");
var leftKeyDown:Boolean = false;
var rightKeyDown:Boolean = false;
var mainSpeed:Number = 7;
vector.addEventListener(Event.ENTER_FRAME, moveChar);
function moveChar(event:Event):void{
if(leftKeyDown){
if(vector.currentLabel!="andando"){
vector.x -= mainSpeed;
vector.scaleX=-1;
vector.gotoAndPlay("andando");
}
} else {
if(rightKeyDown){
if(vector.currentLabel!="andando") {
vector.x += mainSpeed;
vector.scaleX=1;
vector.gotoAndPlay("andando");
}
}
}
}
stage.addEventListener(KeyboardEvent.KEY_DOWN, checkKeysDown);
function checkKeysDown(event:KeyboardEvent):void{
if(event.keyCode == 37){
leftKeyDown = true;
}
if(event.keyCode == 39){
rightKeyDown = true;
}
}
stage.addEventListener(KeyboardEvent.KEY_UP, checkKeysUp);
function checkKeysUp(event:KeyboardEvent):void{
if(event.keyCode == 37){
leftKeyDown = false;
}
if(event.keyCode == 39){
rightKeyDown = false;
}
}
FYI: "parado" is my idle animation and "andando" is my walk animation.
It's not stopping at frame 1, it's just being sent back to frame 1 all the time. Consider what happens when you hold down the button for a few seconds:
rightKeyDown starts as false. No code in that branch is executed.
User holds the right arrow, rightKeyDown becomes true
moverChar checks rightKeyDown, sees it's true and sends the character to "andando".
moveChar runs again, sees rightKeyDown is true but the character is still at the "andando" frame, so it does nothing.
Character goes to frame after "andando".
moverChar runs, rightKeyDown is still true, but the frame is not at "andando" anymore, so it resets back to it.
And that repeats during all the time the user is holding down the key, so it appears to be stuck in frames 1 and 2
A few alternatives to fix this problem:
Change the key frame only when the user presses or releases the button, not every frame in between.
function moveChar(event:Event):void{
if(leftKeyDown){
vector.x -= mainSpeed;
// No frame checks or frame changes here.
}
[...]
function checkKeysDown(event:KeyboardEvent):void{
if(event.keyCode == 37){
leftKeyDown = true;
vector.scaleX=-1;
vector.gotoAndPlay("andando");
// Send the character to the correct frame when the user presses the key.
}
[...]
function checkKeysUp(event:KeyboardEvent):void{
if(event.keyCode == 37){
leftKeyDown = false;
vector.gotoAndPlay("parado");
// Send it back to idle when the user releases the key.
}
[...]
Another option is to store each animation in a movieclip by itself and put them in a container movieclip. So there will be only two frames in the character's symbol, one for the idle animation and the other for the walking animation. In your code you use gotoAndStop instead of gotoAndPlay, so it doesn't matter if it's called every frame.
Edit: Also try to group your conditionals.
} else {
if(rightKeyDown){
if(vector.currentLabel!="andando") {
vector.x += mainSpeed;
vector.scaleX=1;
vector.gotoAndPlay("andando");
}
}
}
can be rewritten as
} else if (rightKeyDown && vector.currentLabel != "andando"){
vector.x += mainSpeed;
vector.scaleX=1;
vector.gotoAndPlay("andando");
}

can you make Keyboard events differ on different pages?

Hey is there a way to have certain keys do one thing on one page and then different on another, as i use
But then on next frame i cant use space bar again to do another task?
Any help would be appreciated
stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDownn);
function myKeyDownn(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.SPACE){
gotoAndPlay("welcome");
}
}
just remove the listener before you leave the frame.
stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDownn);
function myKeyDownn(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.SPACE){
stage.removeEventListener(KeyboardEvent.KEY_DOWN, myKeyDownn);
gotoAndPlay("welcome");
}
}
in the frame "welcome" add the same code again and just change the gotoAndPlay() part.
stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDownn);
function myKeyDownn(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.SPACE){
stage.removeEventListener(KeyboardEvent.KEY_DOWN, myKeyDownn);
gotoAndPlay("a different frame");
}
}