AS3: pass Keyboard control to child movieclip and back to main timeline - actionscript-3

EDIT: I don't know if this is the norm, but I preferred to leave the original question in and add updates. Please, feel free to let me know if I should eliminate the original code snippets and somesuch.
I am trying to create a slideshow-like presentation in flash CS6, using a main timeline with one symbol in each frame and the different animations (some quite complex) in those symbols. Since I'm going to use a presenter remote, I've captured the keystrokes and coded pg_up and pg_down to go to the next and previous frame respectively:
stage.addEventListener(KeyboardEvent.KEY_DOWN, pagerFunction);
var symb:movieClip;
function pagerFunction(e:KeyboardEvent):void
{
var myKey = e.keyCode;
if (myKey == Keyboard.PAGE_DOWN){
if (symb != null){
//some code that allows to control the symbols timeline forward
} else {
nextFrame();
}
}
if (myKey == Keyboard.PAGE_UP){
if (symb != null){
//some code that allows to control the symbols timeline backward
} else {
prevFrame();
}
}
The problem I'm having is the following. I've added framelabels and stop(); code inside the symbol animations where I needed to control the step from one animation to the next one. However, after having tried numerous solutions on the web, I haven't been able to succeed having the symbols react to pg_up and pg_down as if they were part of the main timeline.
To sum up, what I need to solve is this:
Enter Main timeline Frame
Identify symbol instance (labeled as _mc)
Inside symbol timeline, play from first frame (labeled '0') until next labeled frame ('1' and so on)
stop and wait for next pg_down to start playing from next labeled frame to the following (i.e. '1'-'2'), or pg_up to start playing from the previous labeled frame (i.e. '0' to '1') (for this, I would use a variable to keep track.
on last frame (labeled 'final') exit symbol focus and return keyboard control to main timeline to allow pg_down and pg_up to move to the next / previous frame. on pg_up on symbol.currentFrame == 0, do same.
BTW, if there's a better way to achieve this, I'm open (and quite desperate) for better suggestions / solutions.
Thank you so much to anyone who can help!
Edit: Ok, I guess I wasn't too clear on the issue, so I'll try to add a bit to this:
addEventListener(KeyboardEvent.KEY_DOWN, mc_pagerFunction);
var lbl:String;
var counter:Number = 0;
function mc_pagerFunction(e:KeyboardEvent):void {
var myKey = e.keyCode;
if (myKey == Keyboard.PAGE_DOWN){
lbl = this.currentFrameLabel;
if (this.currentFrameLabel == 'final'){
stop();
stage.focus = this.parent; //which would be the main timeline
} else if (Number(lbl) == counter){
this.gotoAndStop(lbl);
counter++;
} else {
this.gotoAndPlay(lbl);
}
}
if (myKey == Keyboard.PAGE_UP){
lbl = this.currentFrameLabel;
if (this.currentFrameLabel == '0'){
stop();
stage.focus = this.parent; //which would be the main timeline
} else if (Number(lbl) == counter){
this.gotoAndStop(lbl);
counter--;
} else {
this.gotoAndPlay(lbl);
}
}
}
Now, this bit is the behaviour I'd like to see inside the symbol when the main timeline goes into the next frame, thus being able to use the main timeline as sort of slideholder and the real thing happening inside the symbol.
Btw, I'd like to try and keep all code within the main action layer, not in the symbols. I tried that, shifting focus to the symbol and it didn't work either, and having code all over the place grates against my nerves ;).
I hope this throws some light on what I'm stuck at.
Again, any help is appreciated. Thanks all in advance
UPDATE:
Please someone help me out here!
This is what I'm trying. Logically, it makes all the sense in the world, except that it doesn't work.
var symb:MovieClip;
symb = MovieClip(root); //assign symbol I want to be controlled by pg_up/pg_down
symb.focusRect = false;
stage.focus = symb; //focus on current symbol
symb.addEventListener(KeyboardEvent.KEY_DOWN, mc_pager); //add keyboard event listener
function mc_pager(e:KeyboardEvent):void{
var myKey = e.keyCode;
if (myKey == Keyboard.PAGE_DOWN){
do{
symb.play(); // it plays, then checks if the lbl is null or final, then quits
} while (symb.currentFrameLabel == null && symb.currentFrameLabel != 'final');
symb.stop();
symb.removeEventListener(KeyboardEvent.KEY_DOWN, mc_pager);
stage.focus=MovieClip(root); //return focus to main timeline (in the next keyframes, the focus is on the nested _mc
}
if (myKey == Keyboard.PAGE_UP){
do{
symb.prevFrame();
} while (symb.currentFrameLabel == null && symb.currentFrameLabel != '0');
symb.stop();
symb.removeEventListener(KeyboardEvent.KEY_DOWN, mc_pager);
stage.focus=MovieClip(root);
}
}
Where am I being to moronic to get it right? Please, guys, you're the experts, I need your advice here. Thanks!
UPDATE:
Doing a trace on symb, it seems like as soon as it enters the function, it forgets the initial assignment (symb = MovieClip(root)) and shows null. Why?

In this sample, I created a basic proof of concept where I have a circle MC with an instance name of "c" on the main timeline. Within this mc, I created with 2 keyframes inside with stop actions on both. I colored the circle a different color on frame 2 and labeled it as "two".
In the Main timeline I have the following code:
import flash.events.KeyboardEvent;
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyEvt);
function keyEvt(e:KeyboardEvent):void{
if(e.keyCode == Keyboard.PAGE_DOWN){
trace("down");
c.gotoAndPlay("two");
}
}
This should help form a foundation for your code as long as you stick with targeting the symbol through direct reference and ensure your keyboard event is attached to the stage.
Also, always stick with getting a basic working version down first. I.E. Check to see if your keyboard listeners are working for your target object and then build additional functionality off of that.

Related

Adobe Animate (HTML5 Canvas) check timeline position of two movie clips and then display another movieclip if both movieclips are on frame 2

In Adobe Animate (HTML5 Canvas) I need to check if two buttons have been clicked on and advanced to the second frame and if both have then display a movieclip.
I am new to programming and not sure how to even begin. I thought of using eventListner or an if/else statement. Not getting either to work. Any help would be greatly appreciated.
I'll try and answer the question to my knowledge, hopefully, it is simple enough to follow, but I'm sure there are probably better ways to write these functions.
buttonClick(evt) allows the buttons to be toggled on and off, assuming that frame 0 of the movieclips handles the off state of the buttons and frame 1 handles the on state. A function is then called on every click to check the states of the buttons.
checkButtonStates() is a conditional statement that just checks the current frame of the buttons, and if both are at 1 the movieclip is displayed and played.
const button1 = stage.children[0].button1_mc;
const button2 = stage.children[0].button2_mc;
const movieclip3 = stage.children[0].movieclip3_mc;
button1.addEventListener("click", buttonClick);
button2.addeventListener("click", buttonClick);
function buttonClick(evt) {
button = evt.currentTarget;
// check current frame of button and changes frame
if (button.currentFrame == 0){
button.gotoAndStop(1);
} else {
button.gotoAndStop(0);
}
checkButtonStates();
}
function checkButtonStates(){
// if both buttons have been clicked hide buttons and play movie
if (button1.currentFrame == 1 && button2.currentFrame == 1){
showButtons(false);
showAndPlayMovie(true);
}
}
// buttons visible property set by passed parameter
function showButtons(bool){
button1.visible = bool;
button2.visible = bool;
}
// changes visible property of movie by passed parameter. If movie is visible the movie is played.
function showAndPlayMovie(bool){
movieclip3.visible = bool;
if (movieclip3.visible == true){
movieclip3.play();
}
}

AS3 - how to best use variables to effect functionality on different frames

I'm currently building a 50 button interactive display, it needs on a specific frame to log 3 button clicks then save a variable or something that 2 slides later will relay whether the user has chosen the correct 3 buttons. This warning is a simple movie clip. Below I listed the 2 frames that need to relate to each other. Please keep in mind I am fairly new to programming Flash and still struggle correct syntax and utilization.
I appreciate any or all input on how I can better accomplish this using Actionscript 3
The below is hiding 3 boxes that will surround the correct answer once clicked. The fl_check36 needs to somehow in the else section send a variable or something i can reference that would let me show the error box movie clip to the user. (I already have a reset button working for that page)
[Frame 36]
MDI_07_box_mc.visible = false;
MDI_08_box_mc.visible = false;
MDI_14_box_mc.visible = false;
// Boxes to be clicked
MDI_07_btn.addEventListener(MouseEvent.CLICK, fl_ClickToShow_14a);
function fl_ClickToShow_14a(event:MouseEvent):void
{
MDI_07_box_mc.visible = true;
}
MDI_08_btn.addEventListener(MouseEvent.CLICK, fl_ClickToShow_14b);
function fl_ClickToShow_14b(event:MouseEvent):void
{
MDI_08_box_mc.visible = true;
}
MDI_14_btn.addEventListener(MouseEvent.CLICK, fl_ClickToShow_14c);
function fl_ClickToShow_14c(event:MouseEvent):void
{
MDI_14_box_mc.visible = true;
}
// Check for boxes correct and go to next frame
MDI_18_btn.addEventListener(MouseEvent.CLICK, fl_check36);
function fl_check36(event:MouseEvent):void
{
if (MDI_14_box_mc.visible && MDI_08_box_mc.visible && MDI_07_box_mc.visible)
gotoAndStop(37);
else
Feedback_07_Wrong_mc.visible = false;
}
This frame just needs to check if the user got the information correct on frame 36 and show or hide the Feedback based on that.
[Frame 38]
stop();
addEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler_2);
function fl_EnterFrameHandler_2(event:Event):void
{
if (globalVar = 1)
Feedback_07_Wrong_mc.visible = true;
Feedback_07_Wrong_mc.gotoAndPlay(2);
}
Reset_Btn.addEventListener(MouseEvent.CLICK, fl_ClickToGoToAndPlayFromFrame_2);
function fl_ClickToGoToAndPlayFromFrame_2(event:MouseEvent):void
{
gotoAndPlay(1);
}
Thanks in advance!
What #Karma said is true. When you declare any variable on frame 36, it is accessible to any other frames that preceed it. You can also do the same by creating another layer called "Variables" with no keyframes in between which stores all your variables. This way, you would have confidence that the variable is acceccible to all the keyframes of the other layer.

Using QWER keys to jump to a specific scene in AS3

TLDR: I need code in action script 3 which will let users press keys like QWER to jump to a specific scene.
So what I'm doing is creating and interactive comic within flash, and to be blunt I didn't know any AS3 code before this and still pretty much know none.
So I'm going to need some help on this one and I think it is worth mentioning that I am using sound in this project.
what I need to know is how to use letter keys (eg. QWER) to act as shorts cuts to jump to specific scenes. What I have so far which is working is this and another version which uses a mouse click instead.
stop(); ( 1 )
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler);
function fl_KeyboardDownHandler(event:KeyboardEvent):void {
gotoAndPlay(currentFrame+1);
}
and of course all this does is advance the frame, which I do need for some sections of dialogue but that's the basis I've been trying to get it to work.
I do know that q = 81, w = 87, e = 69 and r = 82.
Besides that I've got nothing and I need some help real bad.
You need to check which key has been pressed, you can do it like this:
function fl_KeyboardDownHandler(event:KeyboardEvent):void {
if(event.keyCode == Keyboard.Q){
//do what you need to do when Q was pressed
}else if(event.keyCode == Keyboard.W){
//same for W
}
...etc
}
The KeyboardEvent instance contains data about the event itself, part of it being keyCode, which gives the code of the pressed key. Using this property, you can detect which key the user pressed, and react accordingly.
As you understood, you can use gotoAndPlay() and gotoAndStop() to move around your animation.
It gives us the following code :
stop();
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler);
function fl_KeyboardDownHandler(event:KeyboardEvent):void {
if(event.keyCode == Keyboard.Q) {
gotoAndPlay(1); // Back to the start
} else if (event.keyCode == Keyboard.W) {
gotoAndPlay(currentFrame-1); // Back one frame
} else if (event.keyCode == Keyboard.E) {
gotoAndPlay(currentFrame-1); // Forward one frame
} else if (event.keyCode == Keyboard.R) {
gotoAndPlay(100); // Go to 100th frame
}
}
Note that I am using the Keyboard class to get the keyCode associated to a specific key.

Removing Children in AS3

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
}
}

AS3 change item visibility if variable goes below X amount

I've attached a source file below, I'm kinda stuck.
Basically, its an FLA that has a variable that changes (smscounter) based on whatever number is read in from an XML file (on my server). There is a big movieclip called "rewinder" on frame 1 of the main stage. There are left and right buttons that navigate between frames within that movieclip "rewinder". What I'm trying to do in theory is:
if(frame != 2) {button_right.visibility = true};
if(frame == 2 && smscounter > 5) {button_right.visibility = true};
if(frame == 2 && smscounter < 5) {button_right.visibility = false}
I've been told that won't work simply because once a variable (visibility) is set, it's not going to just continually check it, so I have to dispatch an event? I've tried 3-4 tutorials and I can't get any to work.
Now a few things:
- I would LOVE to avoid anything super complicated. All I need is on frame 2 for the button to not be there IF smscounter is below 5. Other tutorials required another class and document class, but I couldn't get them working
- The buttons are currently outside the rewinder movieclip. I put them inside and on each frame, but then I couldn't get them to react to a rollover.
- The code is about as optimized as if a first grader wrote it, mainly because I'm a designer and I've been having help along the whole way with this.
- Greensock LoaderMax is being used to put the videos and sound in. Not super relevant to the problem, I just left them in there to give a better picture of what I'm working on.
Link to FLA and source files:
http://www.mediafire.com/download.php?ejy6j9h9r1c1829
you can add this code to the main timeline
looks like you can only go to frame 2 and 3, but you have a total of 21 frames (from voltagebar) that's why I used the numbers instead of 1 and totalFrames.
rewinder.addEventListener(Event.ENTER_FRAME,checkButtons);
function checkButtons(e:Event):void{
if(rewinder.currentFrame <= 2){
button_left.visible = false;
}else{
button_left.visible = true;
}
if(rewinder.currentFrame >= 3){
button_right.visible = false;
}else{
button_right.visible = true;
}
}