AS3. How to change character's template in adobe flash cs5 using AS3? - actionscript-3

I'm creating flash game. Here will be abillity to choose one of two (or more) character's. So I have in library created symbol hero. It have 7 animations on click (moving, jumping, attacking etc..)
So I want to create something like hero 2, that player could choose which one likes more. Just how to do that? Create new layer in hero and add animations or how?
I'm asking that because in Action Script 3 I'm adding hero in this case and It always will add the same:
private function create_hero()
{
addChild(Hero);
Hero.gotoAndStop("stay");
Hero.x = stage.stageWidth/2;;
Hero.y = ground.y - 60;
Hero.x_speed = 0;
Hero.y_speed = 0;
}
Maybe here is abillity to make something like that layer2.addChild(Hero);?
Or I need to create new symbol hero2? I don't like this idea, because I have long code to control hero, so for every character I'll need to dublicate code. Could you help me? Thank you.

The proper way is to dynamically create an instance Hero at game start based on the game player's selection. You indeed create two (or more) symbols in Flash CS, with common frame labeling (you can use different animation lengths for different heroes), then, once you've got your hero selection (hero1,hero2,hero3 etc, regardless of their amount) you get the class name from selection and get your Hero variable to be assigned an instance of the respective class. An example:
static var heroes:Array=[hero1,hero2,hero3]; // note: symbol names!
var Hero:MovieClip; // note, not "hero1" or anything, but general MovieClip type
public function selectHero(what:int):void {
// this is called with correct "what", design yourself. I use array index
var whatHero:Class = heroes[what]; // get selected hero symbol
if (Hero && Hero.parent) Hero.parent.removeChild(Hero);
// clean up previous hero. Drop listeners here, if any
Hero = new whatHero(); // get new hero
// process as usual, don't forget to "addChild(Hero)" somewhere
}
How this works: First, you give the player a hero selection dialogue, and call selectHero with proper value of what (0 for hero1, 1 for hero2, etc, as you make your heroes array). Then, the whatHero variable is assigned the corresponding class (yes, one can assign classes to variables in AS3!) And then the class gets instantiated via new construction, and the resultant movie clip is then assigned to Hero variable. After this is done, you can use your hero as before.

Related

Jumping back and forth inside a Movieclip with a button?

So, I'm very much a beginner in AS3. I've been reading and figuring out things as I go, though I can't wrap my head around this.
So, I have 4 frames. Each frame has a different movie clip, MC1,MC2,MC3,MC4
Inside those four movie clips, there is another movie clip with the same instance name for each: BC, and inside that movie clip there are two frames. Frame 1 has a dot, and frame 2 does not.
MC1>BC>(2 frames)
MC2>BC>(2 frames)
and so on....
What I'm trying to do: I wanted to see if there was any way to control the frame navigation of BC inside all four MC clips at the same time with one button.
I want to switch back and fourth between the two frames inside the BC movie clip.
I'm at a loss, I've tried quite a few things.
You should be able to do so by giving them all the same instance name (so long as there is only ever one of them on screen at once).
So lets say you have a button that spans all 4 frames with an instance name of navBtn and you gave each of the MC1-4 clips the same instance name of MC. You could do the following on frame 1:
navBtn.addEventListener(MouseEvent.CLICK, navBtnClick);
function navBtnClick(e:Event):void {
if(MC.BC.currentFrame == 2){
MC.BC.gotoAndStop(1);
}else{
MC.BC.gotoAndStop(2);
}
}
Reading your question again, perhaps what are looking for is to have each clip automatically go to the same frame for their BC child when they load? If that is the case, then follow the example in the comment on your question by #Organis. Here is one way you could accomplish this:
Create two variable on frame one of your main timeline:
var BC_NAV_CHANGE:String = "BC_NAV_CHANGE";
var BC_CurFrame:int = 1;
Then, when you need to change the frame of the BC objects, do the following:
//create a function that you call when you want to change the BC frame
function toggleBCFrame(e:Event = null){
MovieClip(root).BC_CurFrame = MovieClip(root).BC_CurFrame == 1 ? 2 : 1;
//the line above is a if/else shorthand, that is setting a new value to the `BC_CurFrame` var,
//if the current value is `1`, it will set it to `2`, otherwise it will set it to `1`
MovieClip(root).dispatchEvent(new Event(MovieClip(root).BC_NAV_CHANGE));
//this line (above) dispatches a event telling anything that's listening that the variable has changed
}
If the code above is on the main timeline, you can forgo all the MovieClip(root). parts of the code.
Now, on the timeline of your BC MovieClip(s), put the following code:
//create a function that goes to and stops at the frame stored in the global variable
function updateFrame(e:Event = null){
gotoAndStop(MovieClip(root).BC_CurFrame);
}
//next listen for the BC_NAV_CHANGE event, and call the above update function above any time that event happens
MovieClip(root).addEventListener(MovieClip(root).BC_NAV_CHANGE, updateFrame);
//lastly, call the update function right away so when the BC clips loads it immediately goes to the correct frame
updateFrame();

Trigger a function when specific frame number is reached - AS3

I wanted friends, do the following when my MC get a determanido internal quandro, it triggers a function to another MC. for example when the ball hit the wall, a person goes to search - la, I have tried using :
("root") {root.MC.play ()}
Translation from comments:
Friends, I have an MC_1 with 10 frames, when it reaches frame 5, I want another movieClip MC_2 to respond (eg: to move or fade etc)
creating a ENTER_FRAME listener for your MC_1 is the easiest way to achieve this
MC_1.addEventListener(Event.ENTER_FRAME,respond);
function respond(e:Event):void{
if(MC_1.currentFrame>=5)
MC_2.gotoAndPlay(2);
//or any other respose you want from MC_2
}
addFrameScript can be used in AS3 to specify a function to execute on reaching a MovieClip frame.
MovieClip.addFrameScript(index:int, func:Function);
A sample implementation of this:
// addFrameScript's index is zero Based, hence 4 means frame 5
MC_1.addFrameScript(4, funcToExecute);
function funcToExecute():void{
// this will get called when MC_1 reaches frame 5
// do stuff here, like manipulating MC_2, etc...
}

Square bracket notation to dynamically load library items?

So I've spent an embarrassing number of hours trying to save myself a few minutes and make my code a bit neater, and Google has produced nothing, so now I come crawling to stackoverflow. The problem is with square bracket notation + library items:
So let's say you have a MovieClip called "myMC_5", and you want to set its X position to 0..
myMC_5.x = 0;
..and if you don't want to hard-code the name of the MC but instead you want one line of code to move a specific MovieClip based on a variable, you could do something like this:
var selectMC = 5;
root["myMC_"+selectMC]x = 0;
..and this will have the exact same effect as myMC_5.x = 0, except that this time you must specify the location ("root" or "this" or something).
THE PROBLEM:
I'm working on a game in which the graphic for the background is loaded from the library, and it's different for each level. The initial loading of the vector from the library looks like this:
private var land:vector_land0 = new vector_land0();
..and this works fine, but it only loads that one specific vector. There should be about 30 or more. I'd like to just have 1 line of code in the constructor to load any of them, based on a variable which keeps track of the current level, like this:
private var land:["vector_land"+theLevel] = new ["vector_land"+theLevel]();
..but that doesn't work. I get syntax errors ("expecting identifier before leftbracket") because you need to specify the location of the object, like in the first example:
root["myMC_"+"whatever"].x = 0;
..but this library item has no "location". So, how the heck do I dynamically load a vector from the library? It's not "on the root", or anywhere else. It has no location. I refuse to believe that the standard method for accomplishing this is to create 30 different classes or write a giant block of code with 30 "if" statements, but searching Google has found nothing. :(
It sounds like you're looking for getDefinitionByName(), which you could use to do something like this:
import flash.utils.getDefinitionByName;
private var LevelVectorClass:Class = getDefinitionByName("vector_land" + theLevel) as Class;
private var land:Object = new LevelVectorClass();
This is a horrible way to solve the situation, I don't recommend using square brackets anywhere but arrays. I recommend you putting the "lands" into a LandContainer MovieClip, each frame of that MovieClip would container 1 graphic. It is much cleaner, and you could create constants to store the "identity" of the frames.Example:
var land:LandContainer = new LandContainer();
land.gotoAndStop(FIRST_LEVEL); //FIRST_LEVEL is a constant integer
You can even reuse this LandContainer instance because you can set it's visibility, remove from the display list, set it's frame to the next level without creating another instance. On second thought, I would write a wrapper for this class. Aka link it to your own class which extends the MovieClip class and create custom functions, fields... etc..
This dynamic thing is horrible, hard to maintain, and not efficient at all. Don't know why did not they delete it from AS3... they should have.

AS3 Using Many Event Listeners Causing Problems, How to Reduce?

Confusing title, my bad.
Basically, I have a list of names. Looping through, I add a MovieClip, Set 2 properties to it, the name, and an ID. The MovieClip is at the same time made to function as a button and I add 4 listeners, mouse up, over, down, or out. I do this with every name. The function each one is set to is the same.
EX: enemyButton[i].addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
The enemyID turns up "not valid property," time to time when I click, it doesn't crash at all, but sometimes I have to hit the button a few times.
I have narrowed the problem down to having to be caused by the listeners.
The function as simple as:
EX: function mouseUpHandler(e:MouseEvent):void { enemySelected(e.target.enemyID); }
My question is, is too many listeners likely to be the problem? and how can I reduce them?
Here's a snippet of the loop:
var C:Class = Class(getDefinitionByName(enemies[i]));
var c:* = new C();
c.gotoAndStop(1);
enemyButton[i].enemyID = i;
c.name = "select" + i;
c.enemyID = i;
trace(c.enemyID);
enemyButton[i].addChild(c);
enemyScroll.addChild(enemyButton[i]);
enemyButton[i].enemyName.text = info[i][Const.NAME];
enemyButton[i].setChildIndex(enemyButton[i].getChildByName("enemyName"), enemyButton[i].numChildren-1);
Thanks.
If enemyButton is a MovieClip (created via attachMovie, maybe) and not strongly typed as a EnemyButton class, then the ID property becomes dynamic. In this situation, if your list of names contains incorrect data (missing ID field, maybe), then the ID property will remain undefined on some instances of the MovieClip.
You can check the list of data used to generate movie clips. You can run into the same error if you have blank lines in your data.
This has nothing to do with event listeners.
So you just want to generate a bunch of buttons with unique properties and know what button was clicked last. Generally it is very bad idea to implement button logic outside button object. Why? Because you work with object oriented language. Good news is that you work with as3 and it treats functions as objects, so you can assign function to var like this:
var callback:Function = function(name:String, enemyId:int){ /*do something*/ }
And.. you can pass function as a parameter to another function
function setCalback(func:Function){}
button.setCallback(callback);
So, what you really need is to create your own button class, add listeners inside it, add handlers(static handlers will reduce memory usage) and pass callback function to it, that will be called when user clicks button.
Don't mean to spam this much but this was easily fixed, though the responses might have been a better method.
I just had to change target to the currentTarget, that then allowed clicking anywhere on the "button" to work. Whereas before the target varied from childs added to it.
So, solved.
Thanks for the help.

AS3 - Displaying points gained above the player

So, I am adding this text field to my container MC whenever a certain condition is met.
In this case, I am trying to display the number of points gained above a playerMC whenever he grabs a coin. Kind of like the old Mario Games whenever you would step on a Goomba and points would appear above the dead Goomba.
I'd like to be able to assign the "points" text field to a "Text.as" file so I could just control the text field's behaviors from there instead of from within my Document Class.
I know how to create a text field from the document class, but I can't seem to create an empty text field on the stage and then convert it into a movie clip so that I can assign it a base class.
Anyone know of a good way to handle this situation? Any ideas you might have.
It's most efficient to just create the textField via code in the contstructor of your Text.as class. However, if you're set on doing it in the flash IDE... create your dynamic text field, give it an instance name, then convert it to a MovieClip with F8. Go to the library and enter you're new movieClip's properties, set the base class to your Text.as file.
Your class (which encapsulates the textField) should then start out looking something like this:
package {
public class Text extends Sprite {
public var myTextFieldInstanceName:TextField;
public function set text(val:String):void { myTextFieldInstanceName.text = val; }
public function get text():String { return myTextFIeldInstanceName.text;}
public function Text(defaultText:String){
text = defaultText;
}
}
}
In order to set the base class, you need to do the same thing that I recommended you do for your Bullet and Impact movieclips. You perform a linkage by selecting "Export to Actionscript". You can tell it what class to look at for its behavior. Then just addChild it to your playerMC (after adjusting x and y values of course).