button inside a movieclip that changes depending on the frame - actionscript-3

I'm making a dynamic map of France going from Roman times to 2014 and I have a problem.
Most of my interface is working except for one feature that requires a lot of mc inside the main movieclip.
I can't post pictures so i'll try to explain what i did.
I have a main movieclip ("france_map"). Inside it, i have several layers including one called "rulers". In this layer, I have the timeline of every king/president of France.
We'll focus on two of them: Sarkozy (frame 2007 to frame 2012) and Hollande (frame 2013 to frame 2014).
The mc "sarkozy" is only accessible between 2007 and 2012. On frame 2013, it disappears, replaced by the mc "hollande".
When I click on one of them from root, a biography of the one concerned opens.
It works thanks to that code:
france_map.sarkozy_btn.addEventListener(MouseEvent.CLICK, fl_sarkozy_btn);
function fl_sarkozy_btn(MouseEvent: Event): void {
sarkozy.visible = true;
close_fiches_btn.visible = true;
close_arbre_btn.visible = false;
sarkozy_txt.visible = true;
};
france_map.hollande_btn.addEventListener(MouseEvent.CLICK, fl_hollande_btn);
function fl_hollande_btn(MouseEvent: Event): void {
hollande.visible = true;
close_fiches_btn.visible = true;
close_arbre_btn.visible = false;
hollande_txt.visible = true;
};
But, I have two button I use to navigate the timeline (controlled by that code:
/* Avancer ou Reculer d'un an */
flecheg_sym.addEventListener(MouseEvent.CLICK, fl_gotoprev);
function fl_gotoprev(MouseEvent: Event): void {
for each(var item: MovieClip in maps) {
if (item.currentFrame > 0) {
item.prevFrame();
} else {
item.nextFrame();
}
}
fleched_sym.addEventListener(MouseEvent.CLICK, fl_gotonext);
function fl_gotonext(MouseEvent: Event): void {
for each(var item: MovieClip in maps) {
if (item.currentFrame > 0) {
item.nextFrame();
} else {
item.prevFrame();
}
}
}
When I use these button, all timelines move together. It works.
My problem is that:
when I reach frame 2013 ("sarkozy" disappears, "hollande" appears), the new button ("hollande") doesn't work. And when I go back to 2012 ("hollande" disappears, "sarkozy" appears), "sarkozy" doesn't work anymore either.
I don't understand the problem (i'm fairly new at as3 and flash).
If i wasn't clea enough (english is not my first language), tell me, i'll try to explain more.
Thanks for your help.
Jeryl

And when I go back to 2012, "sarkozy" doesn't work anymore either
If you want to use MovieClip as a navigation instrument you should master it. When you go back from current keyframe that contains new assets and logic, and I assume previous frame isn't keyframe with listeners and logic, you will see graphics without any binded scripts. Briefly speaking, reassign your listeners for the buttons, use constant movieclip names, design your timeline appropriately and all be ok.

Related

Trying to make a button that target specific Movie Clip properties that is located within multiple layers of Movie Clips

I want to change the opacity of a specific MovieClip (named: Red_mc) within multiple layers of Movie Clips (example layer hierarchy : Character_mc > arm_mc > weapon_mc > Attribute_mc > Red_mc).
But I also have frame by frame animation within Character_mc (each containing and using the same MovieClip). I want the button to change the properties of all the Red_mc within each frame).
I've learn Adobe Animate for a while now but I've just started learning ActionScript recently,thus I'm very new in this language. Basically I'm just trying to make a somewhat "simple" character profile "page". I've tried a few method, but they have lots of limitation. Below is what I used for a single framed Movie clip
function fl_ClickToHide(event: MouseEvent): void {
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.IntelligenceW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.AgilityW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.StrengthW.visible = true;
}
button_7.addEventListener(MouseEvent.CLICK, fl_ClickToHide_2);
function fl_ClickToHide_2(event: MouseEvent): void {
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.StrengthW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.IntelligenceW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.AgilityW.visible = true;
}
button_8.addEventListener(MouseEvent.CLICK, fl_ClickToHide_3);
function fl_ClickToHide_3(event: MouseEvent): void {
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.StrengthW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.AgilityW.visible = false;
Idle_mc.Idle_hw_mc.CrystalW_mc.Attribute_mc.IntelligenceW.visible = true;
}
This works btu there's lots of limitaion, eg. when there's multiple single framed within the movie clip then it wouldn't work.
My goal is to make a button that when clicked, it'll search for a specific MovieClip and then edit the the properties of the Movie Clips within it.(ie. Red, green and Blue).
TD;DR: So is there a way for the code to search for the a target specific Movie Clip across multiple layers of Movie Clips within a frames?
thanks hope what i said make sense.
Info №1. Objects that are not in the current frame do not exist at the moment (for your script, at least).
Info №2. Mixing scripts and frames is a brave thing to do. Because there's a lot of pain and suffering and misery lies ahead once you decide to go that way.
If I had a task of programming a lot of pieces spread across complicated hierarchy, I think I'd do the following.
First, I'd devise a shared data class that is available from any point of your application.
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
public class AppData
{
static public const D:Object = new Object;
static public const E:Event = new Event(Event.CHANGE);
static public const I:EventDispatcher = new EventDispatcher;
static public function has(key:String):Boolean
{
return D.hasOwnProperty(key);
}
static public function read(key:String):*
{
return D[key];
}
static public function write(key:String, value:*):void
{
if (value === null)
{
delete D[key];
}
else
{
D[key] = value;
}
I.dispatchEvent(E);
}
}
}
Now, if you want certain clip to behave in a certain way, without actually knowing, where this clip is on your app hierarchy might be. For example, you want to control its alpha-transparency. On the first frame of this clip you do:
import AppData;
import flash.events.Event;
// The last argument is important, because timeline objects are
// auto-removed if their parent's timeline instructs so, thus
// you won't be able to locate them and unsubscribe, which,
// in turn, means they will hang in the memory forever.
// Still, if you subscribe them with useWeakReference
// set to true, they will be removed normally
// and unsubscribed automatically.
AppData.I.addEventListener(Event.CHANGE, onChange, false, 0, true);
// Call once in order to forcibly sync the object with the data.
onChange(null);
function onChange(e:Event):void
{
if (AppData.has("red.alpha"))
{
alpha = AppData.read("red.alpha");
}
else
{
alpha = 1;
}
}
Then, once you execute the following instruction, each and every object, watching the red.alpha setting will change its alpha:
import AppData;
AppData.write("red.alpha", 0.3);
The setup above is very primitive, and, probably, can be improved in a number of ways, but that greatly depends on understanding of what you are building there, which I don't have.

setchildindex is creating problems

I have made a simple drag and match game for kids.
I used setchildindex for movie clips to be dragged but when I click next button and go to another frame but movie clips are remaining in the same stage. What should i do?
Here is my code I used: (drag_1, this.numChildren0);.
When I reload it's not working.
drag_1.buttonMode = true;
drag_1.addEventListener(MouseEvent.MOUSE_UP, dropMe_1);
drag_1.addEventListener(MouseEvent.MOUSE_DOWN, dragMe_1);
var back_1X:Number = back_1.x;
var back_1Y:Number = back_1.y;
var hit_2X:Number = hit_2.x;
var hit_2Y:Number = hit_2.y;
function dragMe_1(event:MouseEvent)
{
drag_1.startDrag()
setChildIndex(drag_1, this.numChildren-1);
}
function dropMe_1(event:MouseEvent)
{
drag_1.stopDrag();
if(drag_1.hitTestObject(drop_2))
{
TweenMax.to(drag_1, 0.5, {
x:hit_2X,
y:hit_2Y,
ease:Cubic.easeOut
});
drag_1.mouseEnabled = false;
SoundMixer.stopAll();
}
else
{
TweenMax.to(drag_1, 0.5,
{
x:back_1X,
y:back_1Y,
ease:Bounce.easeOut
});
}
}
You need to remove the MovieClips using removeChild().
Now, why do you need to do that here? Well, this is one of those odd problems you get when you mix the timeline with code. When you place a symbol on the timeline keyframe, the Flash Player will instantiate that symbol when it reaches that frame. After that, any frame on the timeline that updates the symbol (tweens, effects, etc) will do just that, and any frame that lacks the symbol will remove it. However, the Flash Player is very picky about identifying that symbol on each frame of the timeline. When you move it using setChildIndex you are basically breaking the timeline link, and the Flash Player no longer identifies it and removes it based on the keyframes. You'll also find that if you revisit a keyframe that had that symbol, the Flash Player will instantiate a second one regardless if the one you moved is still there. As you can see, it can get pretty messy.

2 distinct event triggered by one button - Flash and AS3

I am completely new using Flash and I am doing a project to enhance my skills.
I wonder if there's a way to connect a button doing 2 different things.
I created a slide button that goes on X axis only using Gesture (Touch) and also I created a movie clip showing a map progressing (changes) I would like to connect them, something like every single frame this button goes on this slide it also plays one frame inside the movie clip and return of course.
I think I made myself clear, as it goes along the axis it plays the movie clip.
is there a way to approach for this idea?
ps:
It looks very advanced
MySprite.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
MySprite.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
MySprite.addEventListener(Event.ENTER_FRAME, fixer);
function onTouchBegin(e:TouchEvent) {
e.target.startTouchDrag(e.touchPointID);
trace("touch begin");
}
function onTouchEnd(e:TouchEvent) {
e.target.stopTouchDrag(e.touchPointID);
trace("touch end");
}
function fixer(e:Event) {
e.currentTarget.x = [int here];
if(runIt){
e.currentyTarget.x += speed;
}
}

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

Why is my button instance forgetting its textfield text and event listener?

I'm working on an assignment due at midnight tomorrow and I'm about to rip my hair out. I am fairly new to ActionScript and Flash Builder so this might be an easy problem to solve. I think I know what it is but I do not know for sure...
I'm developing a weather application. I designed the GUI in Flash CS5. The interface has 2 frames. The first frame is the menu which has a zipcode input and a button instance called "submit". On the second frame, it has another button instance called "change" which takes you back to the first frame, menu.
In Flash Builder 4, I wrote a class to extend that GUI called Application. When Main.as instantiates it, the constructor function runs. However, this was my first problem.
public class Application extends InputBase {
public function Application() {
super();
// Y U NO WORK???
this.gotoAndStop(1);
this.change.tfLabel.text = "Change";
}
}
When I ran debug it tossed a #1009 error saying it could not access the property or method of undefined object. It is defined on frame 2 in Flash CS5. I think this is the problem... Isn't ActionScript a frame based programming language? Like, you cannot access code from frame 2 on frame 1? But, I'm confused by this because I'm not coding on the timeline?
Anyway, I thought of a solution. It kinda works but its ugly.
public class Application extends InputBase {
public function Application() {
super();
// Y U NO WORK???
this.gotoAndStop(1); // when app is first ran, it will stop on the first frame which is the menu frame
setButton(this.submit, "Submit", 1);
setInput(this.tfZipCode);
}
private function submitZip(e:MouseEvent):void {
this.nextFrame();
setButton(this.change, "Change", 2);
}
private function menu(e:MouseEvent):void {
this.prevFrame();
setButton(this.submit, "Submit", 1); // if I comment this out, the submit button will return to the default text label and it forgets it event.
}
private function setButton(button:ButtonBase, string:String="", action:uint=0):void {
button.buttonMode = true;
button.mouseChildren = false;
button.tfLabel.selectable = false;
button.tfLabel.text = string;
switch (action) {
case 1:
button.addEventListener(MouseEvent.CLICK, submitZip);
break;
case 2:
button.addEventListener(MouseEvent.CLICK, menu);
break;
default:
trace("Action code was invalid or not specified.");
}
}
}
Its not my cup of tea to run the set button function every time one of the button instances are clicked. Is this caused by frames or something else I maybe looking over?
I believe you have two keyframes & both have an instance of the button component called button.
If you are working on the timeline try putting the button in a separate layer, with only one key frame.
Something like the following:
Ensures that you are referencing the same button every time & not spawning new ones on each frame.