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;
}
}
Related
Hellow again people.
continuing on making the score board, I have not come across a problem with my Keyboard Event.
The reset and start keys works fine but the stop key doesn't stop it rather resets it. I think it might have something to do with me putting the stop command in the reset code as well but I'm not sure how to go around it.
they all work perfect as (btn) but that's no good for me as the monitor will be far away. take a look?
stage.addEventListener( KeyboardEvent.KEY_DOWN, KeysDown);
function KeysDown(event:KeyboardEvent)
//reset the timer with (space)
{
if(event.keyCode == Keyboard.SPACE)
timer.stop();
timeRemaining = 300;
showTime.text = formatTimeRemaining();
// start the timer
if(event.keyCode == Keyboard.ENTER)
timer.start();
// stop the timer
if(event.keyCode == Keyboard.S)
timer.stop();
}
When writing if statements, the curly braces { } must surround the body of the statement (if the body is 1 line then the braces can be omitted).
Always use the braces and you won't run into this problem again.
stage.addEventListener( KeyboardEvent.KEY_DOWN, KeysDown);
function KeysDown(event:KeyboardEvent)
{
if(event.keyCode == Keyboard.SPACE)
{
timer.stop();
timeRemaining = 300;
showTime.text = formatTimeRemaining();
}
// start the timer
else if(event.keyCode == Keyboard.ENTER)
{
timer.start();
}
// stop the timer
else if(event.keyCode == Keyboard.S)
{
timer.stop();
}
}
I have a project where a MovieClip gets copied when clicked and dragged. It is also possible to rotate and scale the MovieClip with arrow keys.
But this only rotates last MovieClip dragged, not last MovieClip clicked. So if I drag a new copy, the previous dragged copies are not able to rotate or scale.
How can I change this to only make the last MovieClip clicked able to rotate and scale, when arrow keys are pressed?
Here is some of the code used (taken and slightly modified from another post):
addEventListener(Event.ENTER_FRAME, moveObject);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
stage.addEventListener(KeyboardEvent.KEY_UP, noKeyHit);
function keyHit(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.LEFT) leftArrow = true;
if(e.keyCode == Keyboard.RIGHT) rightArrow = true;
if(e.keyCode == Keyboard.UP) upArrow = true;
if(e.keyCode == Keyboard.DOWN) downArrow = true;
}
function noKeyHit(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.LEFT) leftArrow = false;
if(e.keyCode == Keyboard.RIGHT) rightArrow = false;
if(e.keyCode == Keyboard.UP) upArrow = false;
if(e.keyCode == Keyboard.DOWN) downArrow = false;
}
function moveObject(e:Event):void{
if(leftArrow) latestClone.rotation -=0.75;
if(rightArrow) latestClone.rotation +=0.75;
if(upArrow) latestClone.scaleY +=0.01
if(downArrow) latestClone.scaleY -=0.01;
}
Thank you
In your code you are scaling and rotating latestClone.
Somewhere outside of this code you are setting the value of latestClone.
If you want to rotate the latest clicked MovieClip, add an event listener to the click:
latestClone.addEventListener(MouseEvent.CLICK, onCloneClick);
function onCloneClick(e:MouseEvent):void
{
var target:MovieClip = e.currentTarget as MovieClip;
latestClone = target;
}
I have a character for a top-down isometric game. The character is to move in eight directions, so eight idle and eight walking animations. I have the walking animations working [except for diagonal walking animations, I get a still frame for those] but if I try to add the idle animation, my walking animations get borked completely.
I'm trying to get the character to go into the idle animation based on what direction they were facing [like if they're going left, the idle will be left, if they're going diagonally up and right, then the idle will be up and right, etc.] but if I try any sort of idle code, the walk animations do not play and the idle will always be in only one direction.
Here's what I managed to get working so far:
private var speed = Number;
private var kLeft:Boolean = false;
private var kRight:Boolean = false;
private var kUp:Boolean = false;
private var kDown:Boolean = false;
//[misc code and listeners]
private function onFrame(e:Event)
{
if (kLeft == true){
this.x -= 2*speed;
this.gotoAndStop("WalkSide");
this.scaleX = -1;}
if (kRight == true){
this.x += 2*speed;
this.gotoAndStop("WalkSide");
this.scaleX = 1;}
if (kUp == true){
this.y -= 1.5*speed;
this.gotoAndStop("WalkUp");}
if (kDown == true){
this.y += 1.5*speed;
this.gotoAndStop("WalkDown");}
if (kUp == true && kLeft == true){
this.gotoAndStop("WalkUpdiagonal");
this.scaleX = -1;}
if (kUp == true && kRight == true){
this.gotoAndStop("WalkUpdiagonal");
this.scaleX = 1;}
if (kDown == true && kLeft == true){
this.gotoAndStop("WalkDowndiagonal");
this.scaleX = -1;}
if (kDown == true && kRight == true){
this.gotoAndStop("WalkDowndiagonal");
this.scaleX = 1;}
}//onFrame
private function keyPressed(k:KeyboardEvent)
{
if (k.keyCode == Keyboard.LEFT)
kLeft = true;
if (k.keyCode == Keyboard.RIGHT)
kRight = true;
if (k.keyCode == Keyboard.UP)
kUp = true;
if (k.keyCode == Keyboard.DOWN)
kDown = true;
}//keypressed
private function keyReleased(k:KeyboardEvent)
{
if (k.keyCode == Keyboard.LEFT)
kLeft = false;
if (k.keyCode == Keyboard.RIGHT)
kRight = false;
if (k.keyCode == Keyboard.UP)
kUp = false;
if (k.keyCode == Keyboard.DOWN)
kDown = false;
}//keyreleased
So how do I add in coding that if I release [kLeft] then "IdleSide" is visible, etc?
Here is my current .swf file.
Given your current code, one way you can try would be to separate out your direction handling and walking/idle states.
Right now, it looks like you're doing this:
You set a boolean upon key press and on enter frame you check if that boolean is true, then you walk in that direction.
Instead, you can do this:
Have a set of direction states (booleans in your case) and character states (two booleans for now, one for walking, one for idle)
Upon key press, you set both the direction state and character state (say, from idle to walking + left).
Upon key release, you only update the character state and leave the direction state alone (from walking to idle).
Then, in your enter frame loop, you can look up both the direction and character state as to which animation to play, which would be idle + left.
In the future, you may run in to an issue of having tons of flags/booleans if you decide to implement more character states (say.. "resting", or "running"). It might be worth it at this point to do some research in to other ways to handle this problem.
I would suggest you to rewrite your code in a more legible and organized way. The best way to achieve this is something like this:
first of all, creat a movie clip container for each direction's animation, in this example I will only use 4 directions, so we would have:
leftAnimations_mc
rightAnimations_mc
upAnimations_mc
downAnimations_mc
on each frame separate each animation in one of this ways:
1.- each animation in diferent layers, one animation after another, labeling each animation's start keyframe such as "idle", "walk", "run" and so on.
2.- each animation inside a movie clip ("leftIdle_mc", "leftWalk_mc", etc) and add each animation in a different keyframe in your main animations movie clip: "leftAnimations_mc", and label each frame the same way as the previous eample: "idle, walk, run". (I prefer this way because in case you need to update your animation (making it longer or shorter) its easier just tu update the frame in your inner leftIdle_mc or leftWalk_mc, and having the main leftAnimations_mc (which holds all the other animations) intact.
3.- create a new MovieClip called player_mc, and add each animation container in different layers of this movieClip and set an instance name for each animation movieclip.
in the end you should have something like this:
player_mc -> leftAnimation_mc -> "idle" keyframe -> leftIdle_mc
-> "walk" keyframe -> leftWalk_mc
-> rightAnimation_mc-> "idle" keyframe -> rightIdle_mc
(you got the idea...)
now for the coding:
1.- setup your directions and animations like constants, declare a variable for the current direction and declare a variable for the current animation:
private const LEFT:string = "left";
private const RIGHT:string = "right";
private const UP:string = "up";
private const DOWN:string = "down";
private const IDLE:string = "idle";
private const WALK:string = "walk";
private var currentDirection:string = "right";
private var animation:string = "idle";
2.- add your keyDown and keyUp listeners.
in your keyDown event listener, instead of setting true or false values, set your current direction depending on the key pressed, add the animation you want to call and finally add a new method called updateAnimations() e.g.:
if(k.KeyCode == KeyBoardLeft)
{
currentDirection = LEFT;
animation = WALK;
updateAnimations();
}
3.- on your key up/released event, just change your animation to IDLE and also add the updateAnimations method:
private function keyReleased(k:KeyboardEvent)
{
animation = IDLE;
updateAnimations();
}
4.- finally the updateAnimations and hideAnimations methods:
private updateAnimations()
{
hideAnimations();
switch(currentDirection)
{
case LEFT:
player_mc.leftAnimations_mc.visible = true;
player_mc.leftAnimations_mc.gotoAndStop(animation);
break;
case RIGHT:
player_mc.rightAnimations_mc.visible = true;
player_mc.rightAnimations_mc.gotoAndStop(animation);
break;
}
}
private hideAnimations()
{
player_mc.leftAnimations_mc.visible = false;
player_mc.rightAnimations_mc.visible = false;
player_mc.upAnimations_mc.visible = false;
player_mc.downAnimations_mc.visible = false;
}
as you can see, I've used hideAnimations() to hide all the animations movie clips, and then with a switch I set visible only the animation I want, finally I just goto the current animation key frame:
player_mc.rightAnimations_mc.gotoAndStop(animation);
Hope this is clear enough.
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");
}
Trying to get an animation to play backwards while a button is held down, which works fine, however when it gets to the first frame it just stops and won't loop back around to the last frame of the animation- how might one accomplish this? It seems like I need to break the event for a frame somehow and then start listening again...
backward_btn.addEventListener(MouseEvent.MOUSE_DOWN, setDownTrue);
backward_btn.addEventListener(MouseEvent.MOUSE_UP, setDownFalse);
addEventListener(Event.ENTER_FRAME, checkDown);
var isDown:Boolean = false;
function setDownTrue(e:MouseEvent){
isDown = true;
}
function setDownFalse(e:MouseEvent){
isDown = false;
}
function checkDown(e:Event){
if(isDown == true){
prevFrame();
if(currentFrame == 1){
gotoAndStop(120); //120 is the last frame of the animation
isDown = false;
}
}
}
Thanks!
The ENTER_FRAME event is not your problem, it continues to trigger. However, isDown turns into false on the last frame. You should change isDown = false; to isDown = true; after the gotoAndStop line in order to loop continuously.
I actually just helped a co-worker with this:
myMovieClip //your instance on the stage
lets say you want your movieclip to play backwards on click:
myMovieClip.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, playBackwards);
}
function playBackwards(e:Event):void
{
var frame:int = myMovieClip.currentFrame -1; //get frame before current;
myMovieClip.gotoAndStop(frame); // go to that frame
if(frame == 1) removeEventListener(Event.ENTER_FRAME, playBackwards); //if the frame is the first frame then remove the enterframe event
}
Save yourself some trouble and use totalFrames:
if(currentFrame == 1)
gotoAndStop(totalFrames);
else prevFrame();