Log in

View Full Version : more efficient code suggestions



evan
07-09-2008, 02:33 PM
The following code is for a series of buttons that are movieclips, nested in another movieclip.

There are about 13 in all. This setting this up allows me to click a button, contained in a movieclip and have those buttons remain in their pressed state ("fr1" in pblack_mc is unpressed "fr2" is pressed) _and upon selecting it -no matter what other button is selected they would reset to their pressed states.

This code works, but doing it 13 times is, um...




drawtools.pblack_mc.addEventListener(MouseEvent.CLICK,bpressed);
function bpressed(e:MouseEvent):void{
drawtools.pblack_mc.gotoAndStop("fr2");
drawtools.pred_mc.gotoAndStop("fr1");

drawtools.ppink_mc.gotoAndStop("fr1");
/*drawtools.pblue_mc.gotoAndStop("fr1");
drawtools.pblue2_mc.gotoAndStop("fr1");

drawtools.pgreen_mc.gotoAndStop("fr1");
drawtools.pgreen2_mc.gotoAndStop("fr1");
drawtools.pyellow_mc.gotoAndStop("fr1");
drawtools.pyellow2_mc.gotoAndStop("fr1");
drawtools.porange_mc.gotoAndStop("fr1");
drawtools.porange2_mc.gotoAndStop("fr1");
drawtools.pmagic_mc.gotoAndStop("fr1");*/
}

Medyman
07-09-2008, 05:28 PM
:D...

This reminds me of when I first started coding. My first few projects were FILLED with this kind of code, until it finally dawned on me that there is probably a better, more efficient to do such a simple task. Obviously, you've come to the same realization.

So, let me introduce you to arrays. In this situation, what you should do is assign all of your movieclips to an array. Then, loop through the array and assign your event handlers and gotoAndStop() actions. This way, you're only writing the code once, but it's being executed multiple times. It's not only less typing, but a lot less resource intensive.

So, first take all of your movieclips and assign them to an array. Let's call the array tools for relevance sake, strict data type it to Array and build the array.

var tools:Array = new Array(drawtools.pblack_mc, drawtools.pred_mc, drawtools.ppink_mc);

Note: Of course, you would add all of your movieclips to the array.

Then, loop through the tools array using a for...in loop and assign whatever event handler you want. In this case, it would be a MouseEvent.CLICK handler.

for (var i in tools) {
tools[i].addEventListener(MouseEvent.CLICK, pressed);
}

This loops through the tools array, incrementing i (the index of the array) by 1 (it starts at i=0) with each iteration of the loop. Therefore, when Flash reads it, it's really being sent a series of commands in the following form:

tools[0].addEventListener(MouseEvent.CLICK, pressed);
tools[1].addEventListener(MouseEvent.CLICK, pressed);
tools[2].addEventListener(MouseEvent.CLICK, pressed);
...

Of course, tools[n] is typical array notation meaning the nth element in the tools array (i.e. tools[0] would equal drawtools.pblack_mc).

Now, create the pressed() function that the event handler is calling. Again, you'll need to loop through the entire array, setting each button to the "off" state. Don't worry about turning the current button "on" yet. Once the loop is completed, then turn the current button (the one you just clicked) "on". The code might look something like this:


function pressed(e:MouseEvent):void {
for (var i in tools) {
tools[i].gotoAndStop("fr1");
}
e.target.gotoAndStop("fr2");
}


In the end, all of this:

drawtools.pblack_mc.addEventListener(MouseEvent.CLICK,bpressed);
function bpressed(e:MouseEvent):void{
drawtools.pblack_mc.gotoAndStop("fr2");
drawtools.pred_mc.gotoAndStop("fr1");

drawtools.ppink_mc.gotoAndStop("fr1");
/*drawtools.pblue_mc.gotoAndStop("fr1");
drawtools.pblue2_mc.gotoAndStop("fr1");

drawtools.pgreen_mc.gotoAndStop("fr1");
drawtools.pgreen2_mc.gotoAndStop("fr1");
drawtools.pyellow_mc.gotoAndStop("fr1");
drawtools.pyellow2_mc.gotoAndStop("fr1");
drawtools.porange_mc.gotoAndStop("fr1");
drawtools.porange2_mc.gotoAndStop("fr1");
drawtools.pmagic_mc.gotoAndStop("fr1");*/
}
... TIMES 13

boils down to this:

var tools:Array = new Array(drawtools.pblack_mc, drawtools.pred_mc, drawtools.ppink_mc);
for (var i in tools) {
tools[i].addEventListener(MouseEvent.CLICK, pressed);
}

function pressed(e:MouseEvent):void {
for (var i in tools) {
tools[i].gotoAndStop("fr1");
}
e.target.gotoAndStop("fr2");
}

Much simpler, no? ;)
The logic gets a little bit more tangled when you start to incorporate on/over states as well. I'm not sure if you plan to, but if you do... here (http://www.visualbinary.net/files/tutorials/for-loop/) is an example of it in AS3 using the same technique, just with some adding and removing of event listeners in various loops. It has two states small ("off") and large ("on"). When you roll over it, it goes to the "on" stage and when you click it, it sticks. Click something else and the previous one turns "off" and the new one sticks in the large state. Pretty simple.

Good luck.

evan
07-10-2008, 11:17 AM
That worked great!

One more question:


I am trying something that should be pretty simple:

drawtools.select2_btn.addEventListener(MouseEvent.CLICK,twopressed);
function twopressed(e:MouseEvent):void{

pencils[0].alpha=0;

}in an event works great


but selecting multiple at once, ie pencils[0,1,2,3].alpha=0 is not good

I could just type them all, but I want to do it the smart way.

Initially I did this to create an inteface that changes buttons:




tipint.text_btn.addEventListener(MouseEvent.CLICK,textFrame);
function textFrame(e:MouseEvent):void{

tipint.gotoAndStop("text");
}
tipint.images_btn.addEventListener(MouseEvent.CLICK,imageFrame);
function imageFrame(e:MouseEvent):void{
tipint.gotoAndStop("images");
}


The trouble was I also have to set alpha of unused buttons to zero, dissable listeners, and move unused buttons away from buttons used on the next frame.

SO.. I tried this:
This toggles the z-index of movieclips and allows two ways to toggle them: either with square and circle buttons. or buttons "nested" in each clip.

square_btn.addEventListener(MouseEvent.CLICK, showcircle, false, 0, true);

function showcircle(evt:MouseEvent):void {
var folder:MovieClip = evt.target as MovieClip;
setChildIndex(square_mc, numChildren - 1);
}
circle_btn.addEventListener(MouseEvent.CLICK, showsquare, false, 0, true);

function showsquare(evt:MouseEvent):void {
var folder:MovieClip = evt.target as MovieClip;
setChildIndex(circle_mc, numChildren -1);
}

square_mc.b1_btn.addEventListener(MouseEvent.CLICK, showcircle2, false, 0, true);

function showcircle2(evt:MouseEvent):void {
var folder:MovieClip = evt.target as MovieClip;
setChildIndex(circle_mc, numChildren -1);
}

I think alot of stuff you showed me and I have been reading are starting to click.

I'll post examples later If I have enough time.

hyk
07-13-2008, 11:35 AM
sorrie to bump this thread. evan are you using actionscript 3? I do not remember seeing stuffs like twopressed or bpressed while I was learning as 2.

thanks in advance for answering my queries:D

Medyman
07-13-2008, 01:44 PM
@evan...

So, did you figure out how to do what you were having trouble with? I'm not sure I understand what you're trying to do. Is pencils[] an array that holds all of your movieclips. And when you click one, you want the others to go to alpha 0?

Then, use an array like I showed you in the first post. Just looping thorugh them will eliminate the need to write all of the out.

Let me know if you mean something else.

@hyk...
Evan is using AS 3.0. But, the functions you mention (bpressed, twopressed) are custom functions that Evan has written. They're not native AS 3.0 methods.

hyk
07-14-2008, 10:28 AM
i see... Thanks 4 the answering my qns Medyman :)

evan
07-14-2008, 03:00 PM
Ok,

I hope this explains things a little.

First off, I needed a smart(er) way to have many buttons (movie clips with two frames) with over states work and stay in a pressed state when selected.

I found a way, BUT it was waaaay too long -it was based on some advice Mendyman posted earlier showing me how to have buttons withing movie clips work/navigete/respond to the main timeline.

The next problem was, as I had waaay too many of these to deal with, in this post -again mendyman demonstrates arrays.

the next thing I wanted was to have MANY of these types of toolbars -each contained withing it's own MC.

Notice how the pulldowns overlap other buttons, for example. That's why I let go of using "alpha" -it was a cop-out anyway.



I wanted to avoid frames, so I opted to use add/remove child to place and "stack" them.

Medyman
07-15-2008, 11:33 PM
I see what you mean. With the sheer size of functionality that you're programming, without using OOP, that repetition of code is expected to occur.

The application you're coding, if coded properly, should be done using object oriented programming.

evan
07-16-2008, 12:34 AM
I know, it's just like taking the jump into a cold pool of water and knowing you need to but once you're in it's ok.

Any starting advice?

otherwise what the hell I've gone this far, why stop now?

Medyman
07-16-2008, 01:50 AM
I know, it's just like taking the jump into a cold pool of water and knowing you need to but once you're in it's ok.

Any starting advice?

otherwise what the hell I've gone this far, why stop now?

Your jumping in the water analogy is very apt. I really wouldn't give any advice except to say jump in...the water's fine :p

You asked about efficient code, so that's your answer. Otherwise, what you're doing isn't wrong but there are limitations to developing this kind of thing with that kind of architecture. Well, maybe not limitations but inefficiencies (read: redundant code).