I created a movieclip named stickman. In that, I created an animation by drawing a sequence of move in everyframe, so that stickman can run. Now what I want is that when I press a key, the stick man will run from left to right and when I release the key, it will stop. This is my code:
RunningMan.stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN,keypresseddown);
function keypresseddown(event:KeyboardEvent):void
{
var key:uint = event.keyCode;
switch (key) {
case Keyboard.LEFT :
{
RunningMan.play();
RunningMan.x-=10;
RunningMan.scaleX=-1;
if(RunningMan.x<=0)
{
RunningMan.x=0;
}
};
case Keyboard.RIGHT :
{
RunningMan.play(); //play animated run
RunningMan.x+=10;
RunningMan.scaleX=1;
if(RunningMan.x>=stage.width)
{
RunningMan.x=stage.width;
}
};
default: RunningMan.stop();
}
}
However, when I pressed and held a key, it moved from left to right without animated run.
How can I fix it?
Thanks in advance.
EDIT:
I have a movieclip called character containing 3 movieclip named: standing, running and jumping, respectively. When I pressed up arrow key, it would jump, but if I released the key right away, it did not jump high as the jump movieclip could not finish its frames. This is the code:
if (key.isDown(Keyboard.LEFT))
{
gotoAndStop("running");
BGround.x+=speed;
scaleX=-1;
if(BGround.x>=stage.stageWidth)
BGround.x=stage.stageWidth;
}
else if (key.isDown(Keyboard.RIGHT))
{
gotoAndStop("running");
BGround.x -= speed;
scaleX=1;
}
else
if (key.isDown(Keyboard.UP))
{
gotoAndStop("jumping");
}
else
gotoAndStop("standing");
How can I fix that?
First of all, I hope RunningMan is an instance of the class, not the class itself. And if it is an instance, you should really follow common naming conventions for when you share your code with others (like you are doing now) so it would be runningMan.
So 1st, make the 1st frame of the runnigMan's timeline a picture of the man standing still and name it "still" or something. then name the second "running" and extend that like 20 frames or however long your animation is. at the last frame you will have to use timeline code. just one line of gotoAndPlay("running") will cause those frames of 2 to 20 (or whatever) to loop. When you tell the timeline to go to frame 1 from outside the timeline code, it wont loop anymore and will stay on the frame of the man standing still. So from outside when you want the loop to start:
runningMan.gotoAndPlay("running"); // frame 2
To stop:
runningMan.gotoAndStop("still"); // frame 1
Or you could do it from inside the RunningMan class
public function startRunAnimation():void{
this.gotoAndPlay("running");
}
public function stopRunAnimation():void{
this.gotoAndStop("still");
}
And you could use them just by replacing these function names with the ones you have if your code ex( instead of play() it would be startRunAnimation() )
EDIT
What you could do for this problem is to have a boolean variable for when your character is in the air (somewhere in your code where you do collision detection with the ground or where you handle gravity - however it is set up) so that this part of your code know when your character is in the air. And then you could simple test for this however way you need it.
...
if (key.isDown(Keyboard.UP) || this.inAir==true)
{
gotoAndStop("jumping");
}
else
gotoAndStop("standing");
Although if your character does not inheirt from a collidable object that has gravity, friction etc... then you would have to make the inAir property of whatever other class, public or make getter function for it - so that you can access it here. I hope this helps.
Related
I don't know why I can't figure out this problem that is really basics !! (sometimes the brain is tired I guess).
I've got a movieclip with a guitar string.
I want the string to move everytime I click on it.
I've created a movie clip with 2 lables. the first = non movement, the second = movement.
I've placed in the second one a stop(); action. (in order to stop the loop)
I've put this code :
stringOne.addEventListener(MouseEvent.CLICK, accord1, false, 0, true);
public function accord1(e:MouseEvent):void{
var stringOne;
trace("DING");
stringOne.gotoAndStop("first");
}
It works but, of course, it only play the string movement at the first click.
Do you know how I could play the string movement EVERYTIME that I click on the string ?
Thank you very much and sorry for this easy question (little ashamed)..,
EDIT
Ah ! It seems to work with goToAndPlay !
if (stringOne.currentLabel=="premier") {
stringOne.gotoAndStop("default");
} else {
stringOne.gotoAndStop("first");
}
Just a thing, I have to click twice..
(one click = the string vibrate (label2))
(one click again = the string does nothing (going to label 1))
(one click again = the string vibrate (label 2))
Is there anyway to automatically skip the 2nd click (the one that tells the string to go back at label 1), and let do the code like : - When animation of label 2 is finished, automatically go back to label 1 ? –
Presumably, the "movement" label of the string is some sort of animation?
It seems to me what you want in your "guitar string" movieClip is, on the last frame of the timeline animation for "movement", a script that says gotoAndStop('non movement'). The click handler should gotoAndPlay('movement').
Then, when the string 'movement' animation is finished, it will reset itself, so that the next time you click it will play again.
So, your original code is fine (before the edit; but remove the "var stringOne;" since that will break the reference to stringOne). The only thing you need to add is a script in the timeline on the last frame of the movement animation ("first" label?) that says gotoAndPlay("default") (assuming default is the 'non movement' label). You may need a stop() in the timeline frame for "default".
Something like that :
stage.addEventListener( MouseEvent.CLICK, onStageClick);
protected function onStageClick(event:MouseEvent):void
{
switch( event.target )
{
case stringOne:
trace("String one stuff");
break;
case stringTwo:
trace("String 2 stuff");
break;
}
}
Or add your movieClip into a Sprite and listen click event on the Sprite and not on the MovieClips.
Thank you for the answer. I've found an other way, instead of mouse click I've used mouse down for going to frame 2 and mouse up for going to frame 1
I'm creating a quiz with buttons and I'm new to ActionScript 3.0, but very familiar with 2.0.
I have a variable inside of a MC called NextQuestion. When it reaches a certain frame, it changes to 1, then back to 0.
On the main timeline, when NextQuestion == 1, it's supposed to NextFrame();. I can't get it to work though, this is the last thing I'm having trouble with.
This is my main code with 4 buttons, 3 wrong, 1 right. The feedback MC plays an animation, and when it finishes, it sets the VAR NextQuestion to 1, which is supposed to make the main timeline advance to the NextFrame.
stop();
right.addEventListener(MouseEvent.CLICK, rightClick1);
wrong1.addEventListener(MouseEvent.CLICK, wrongClick1);
wrong2.addEventListener(MouseEvent.CLICK, wrongClick1);
wrong3.addEventListener(MouseEvent.CLICK, wrongClick1);
feedback1.addEventListener(Event.ENTER_FRAME, answerRight1);
function answerRight1()
{
if (feedback1.NextQuestion == 1)
{
trace(feedback1.NextQuestion);
nextFrame();
}
else
{
trace("do nothing");
}
}
function rightClick1(ev:MouseEvent):void
{
trace(feedback1.NextQuestion);
feedback1.gotoAndPlay("right1");
}
function wrongClick1(ev:MouseEvent):void
{
trace("wrong");
feedback1.gotoAndPlay("wrong");
}
Any help is greatly appreciated! :)
The nextFrame() method in AS3 doesn't loop trough your movieClips, it just set's the movie clip to the next frame provided there is a next frame, otherwise it does nothing.
you might want to re-write the nextFrame() to:
if (totalFrames == currentFrame)
{
gotoAndStop(1); // or gotoAndPlay(1) if you need
}
else
{
nextFrame();
}
Thats regarding why the movie clip might not start from the beginning.
Another thing that look weird is that you need a FRAME_ENTER event to check if the answer is correct. You must have a lot of spam in the output log. I'd recommend you to totally ditch the ENTER_FRAME event listener for this and do it all with the CLICKED event and dispatching the event from the feedback1 object.
As much as I understand the movie clip plays when you click a button and when the animation is over you want to either progress to next frame or do nothing. If so, on the feedback1 object add a following line in the end of animation for label "right1":
dispatchEvent(new Event("right"));
and instead of the line feedback1.addEventListener(Event.ENTER_FRAME, answerRight1); have:
feedback1.addEventListener("right", answerRight1);
That way you won't need to check the answer on every frame and you don't need to check if the answer is right or not, because when the dispatchEvent(new Event("right")); fires - it's always right.
Hope I didn't misunderstand your question :)
Ok, so I'm a beginner at AS3 and Flash and I managed to put this code together for an animation. A Button called start_btn is supposed to start and stop a movieclip called main_mc. On the first click of the Button, the Movieclip is supposed to play (which it does), however on the second click, the movie stops in the middle of its animation (which I don't want). My question is, when you click the Button a second time, how can i get the Movieclip to finish playing its animation then stop on the last frame?
I thought about using if (main_mc.currentFrame == main_mc.totalFrames); {main_mc.stop(); but the Movieclip still does not stop on the last frame. The Movieclip itself also has a gotoAndPlay(2); command on the last frame so that the animation repeats before the Button is clicked a second time.
here is the code i have:
`start_btn.addEventListener(MouseEvent.CLICK, mainaniS);
function mainaniS(event:MouseEvent):void
{
main_mc.play();
start_btn.removeEventListener(MouseEvent.CLICK, mainaniS);
start_btn.addEventListener(MouseEvent.CLICK, mainaniSt);
}
function mainaniSt(event:MouseEvent):void
{
if (main_mc.currentFrame == main_mc.totalFrames);
{main_mc.stop();}
start_btn.removeEventListener(MouseEvent.CLICK, mainaniSt);
start_btn.addEventListener(MouseEvent.CLICK, mainaniS);
}`
Try main_mc.gotoAndStop(main_mc.totalFrames).
I was going to provide a quick and dirty solution, but decided instead to try and explain a few of the issues with your current implementation and attempt to refactor and explain and better one. Unfortunately I don't have access to Flash right now, so the code is untested.
You're adding and removing event listeners often, which is generally a bad idea. Instead, since you're using a single button to perform multiple functions it would make sense to track the button state in a separate variable. In this case, a boolean for whether or not the movieclip is currently playing.
var playing:Boolean;
Now we can combine the mainaniS and mainaniSt into one and perform a different action based on whether or not the movieclip is playing, and just keep the one eventlistener on the button. I've also taken the liberty of naming the method something more meaningful:
start_btn.addEventListener(MouseEvent.CLICK, onStartClick);
function onStartClick(event:MouseEvent):void
{
if(playing) {
playing = false;
}
else {
playing = true;
main_mc.play();
}
}
You may be wondering why we don't call main_mc.stop() in the first block: the reason is that you don't want to stop the movieclip as soon as you click the button, but after the movieclip has finished playing if the button has been clicked. Therefore, we just set playing to false to indicate that we want it to stop later.
Finally, we need to make sure the movieclip stops upon completion, but only if playing is false. To do this we add a listener to movieclip that is called every frame, and checks whether playing is false, and if it's on the last frame. Note that the last frame is actually totalFrames - 1: this is because the frame numbers start from zero rather than one (i.e. if totalFrames is 3, the frame numbers will be 0, 1, 2).
main_mc.addEventListener(Event.ENTER_FRAME, animate);
function animate(event:Event):void {
if(!playing && main_mc.currentFrame == main_mc.totalFrames - 1) {
main_mc.stop();
}
}
All the refactored code together:
var playing:Boolean;
start_btn.addEventListener(MouseEvent.CLICK, onStartClick);
main_mc.addEventListener(Event.ENTER_FRAME, animate);
function onStartClick(event:MouseEvent):void
{
if(playing) {
playing = false;
}
else {
playing = true;
main_mc.play();
}
}
function animate(event:Event):void {
if(!playing && main_mc.currentFrame == main_mc.totalFrames - 1) {
main_mc.stop();
}
}
My flash game exists of a timeline with multiple frames (I know I should avoid the timeline)
The point of the game is a point and click adventure. The object that you are able to pick up get spawned and destroyed accordingly as you enter and leave the room. now my problem is when entering frame 14 (accessibel from frame 12) it creates a piece of paper which you are able to pick up if you have another item. Now my problem is when you can't or don't pick up the paper and go back to frame 12 (only exit is to frame 12), you can't click on any other object and you are basicly stuck on frame 12. When leaving and entering other rooms it works properly but for some reason it doesn't for on the paper on frame 14.
My code to remove objects works as following
In my Main.as Documentclass I have a function that called as soon as the game starts which does the following
if (lastframe == 14)
{
trace (prop.numChildren);
while (prop.numChildren )
{
prop.removeChildAt(0);
}
}
The lastframe variable is established when moving from frames
this function is found on the frame itself (each exit function on it's own respective frame)
function exitKantine(event:MouseEvent):void
{
Main.lastframe = 14;
gotoAndStop(12);
}
The function to remove the prop actually removes it but then causes all other clickable objects to be unusable.
Thanks for looking at my question and thanks in advance for your suggestions
I would say instead of removing children, add it once in the beginning, add all the listeners in the beginning, and toggle the visibility instead of trying to addChild and removeChild every time you want to hide it. Use an array so you can have a few happening at the same time.
something like this:
private function init():void
{
assignVars();
addListeners();
stage.addChild // make sure this is in document class or you are passing stage to the class using it
}
for (var i = 0; i < _thingsAry.length; i++)
{
if (_thingsAry[i] == 14)
{
_thingsAry[i].visible = false;
trace("the visibility of _thingsAry[" + i + "] is " + _thingsAry[i].visible
}
}
It's been a while since I've had to write Actionscript that really needs to integrate with the timeline (in this case, controlling a series of frames that must happen in a certain sequence) and I am trying to figure out what to do.
In the first few frames, I have a button "next_1".
At frame 10, I need to have another button "next_2". I really really need this button to not be on frame one (I could possibly just make it invisible, but that's going to create a clickable area that I don't want).
The problem is, anything I don't put on "frame_1" renders as null in my Document class.
Is there any solution to this? I would rather not have to write my script on the timeline if possible (it seems easier in the long run to keep it in a document class)...
Items on the timeline are created on the fly, so if the playhead has not reached frame 10, next_2 is not created.
Easiest Document-class solution:
Create an array of frame labels like ["label1", "label2"]
Create sectionIndex var and set it to 0
Create a next button on its own layer so it is always showing.
When the next button is clicked, increment sectionIndex, then gotoAndPlay(myLabels[sectionIndex])
Okay, directly lifted from "Real World Flash Game Development":
/**************************************************
* FRAME LABELS *
**************************************************/
private function enumerateFrameLabels():void {
for each (var label:FrameLabel in currentLabels) {
addFrameScript(label.frame-1, dispatchFrameEvent);
}
}
private function dispatchFrameEvent():void {
dispatchEvent(new Event(currentLabel, true));
}
This dispatches an event at each frame label on the timeline.
Then you can just add event listeners for each frame:
addEventListener("name_of_my_framelabel", frameHandler);
addEventListener("another_framelabel", frameHandler);
And write a switch statement to add event listeners for the buttons when they actually show up on the timeline.
private function frameHandler(e:Event):void {
switch(e.type) {
case 'screen_2':
stop();
next_2.addEventListener(MouseEvent.CLICK, click2, false, 0, true)
break;
}
}