Flash AS3 Need help handling animations by script - actionscript-3

Im trying to get a better solution for animating images like fade in slide to another location bump to another location fade out , bring in a new image, fade in, teleport to other location, let it fall down, slide out.
im in a learning progress of getting advanced with classes and my setup is like the following:
1 imgSheet, 1 tweenclass, 1 displayclass, 1 timerclass
so the display creates holderSprites, creates a bitmap out of the imagesheet and places it in the currentholderSprite, than the displayclass activates a animation function that animates the holder by triggering timers and tweens in those classes.
i understand using a timeline would be a easyer solution but this is for script learning purpose.
now my question is: Are there better solutions to handle this kind of animations and data passing other than using switch statements for everything. for example could i pass a tweenvar and timervar to the classes?
if i did so how do i have to handle that variables change them and recall the functions so it becomes a animation?
simple example in script:
i send this to the bitmap creater:
var rCutKongregate:Rectangle=new Rectangle(0,0,400,400);
the bitmap creater makes it a bitmap and places it in a sprite:
public function displayImage(rn:Rectangle, o:Object):void
{
var imgSourceFile:BitmapData=new spriteSheet ;
var imgHolderData=new BitmapData(400,400,true,0x666666);
var rCut:Rectangle=rn;
var pCut:Point=new Point(0,0);
imgHolderData.copyPixels(imgSourceFile, rCut, pCut);
var imgHolder:Bitmap=new Bitmap(imgHolderData);
currentTempSprite.addChild(imgHolder);
}
this is how the animation triggers timers/tweens
switch (loopNumber)
{
case 2 : timersHandling("07"); break;
case 4 : tweensHandling("04"); break;
}
public function tweenHandling(s:String)
{
switch (s) {
case "01" :var sFOTween:Tween=new Tween(object,"alpha",
Strong.easeInOut,1,0,2,true); trace("tween1 started");break;
case "02" :var sFITween:Tween=new Tween(object,"alpha",
Strong.easeInOut,0,1,2,true); trace("tween2 started");break;
public function timersHandling(s:String)
{
var timer01:Timer = new Timer(1000, 1);
var timer02:Timer = new Timer(2000, 1);
var timers:Array = new Array();
timers.push({Object:timer01, name:"timer01"});
timers.push({Object:timer02, name:"timer02"});
switch (s) {
case "01" : timer01.start(); break;
case "02" : timer02.start(); break;
well as you might understand making animations manualy by triggering functions in such a way is prob the most amature way you could do it so help will be welcome.

"Can you pass a tweenvar and a timervar to classes?" - yes, and you should make so that you don't have to track either variable after assignment. "Using a timeline could be an easier solution" - no, although for self-contained objects (that don't contain controls, referenced parts and code) a timeline animation is acceptable. And third, you are hardcoding too much in your code. You can instead use an array of them tweens, triggering and eliminating them as necessary. Indeed, you might want to look at any tween framework, Greensock, TweenMax, TweenIO and probably there are others, they have source code available for study and use, so you can find out how are they working inside.

I'm not clear exactly what you want to see happen but this can probably be done very simply with the greensock tween classes.
see: http://greensock.com/tweenmax

Related

AS3/ AIR Alternative to PrevFrame() (too slow if big movieclip)

I'm having a problem with prevFrame(). In my previous projects, I never had a trouble with it (usage is pretty straightforward), but this one... I don't understand. Everything does what it needs to do, but when I try to go to the prevFrame of my "main movieclip", it takes ages.
Some context: I'm making a dictionary for an ancient language (non-latin alphabet). There are 6.000 glyphs so I had to find a way to make such a complex "keyboard".
var gArray: Array = [gEmpty, clavierUI.g1, clavierUI.g2, clavierUI.g3, (...)
clavierUI.g50
]; //array contaning the buttons for the keyboard (50 instances of the same
//movieclip. This movieclip is made of 6.000 frames, each containing a
//glyph), the fnClavier function makes each of the fifty instances go to its
//respective frame)
var myXML2: XML = new XML();
var XML_URL2: String = "assets/glyphs.xml";
var myXMLURL2: URLRequest = new URLRequest(XML_URL2);
var myLoader2: URLLoader = new URLLoader(myXMLURL2);
myLoader2.addEventListener("complete", xmlLoaded2);
//import the codename for each glyph
function xmlLoaded2(event: Event): void {
myXML2 = XML(myLoader2.data);
}
var xml2: XMLList = myXML2.glyph.code;
function fnClavier(e: Event): void { //transforms the keyboard
for each(var glyph: MovieClip in gArray) {
glyph.gotoAndStop(gArray.indexOf(glyph) + (50 * (clavierUI.currentFrame - 1)));
//the seconde half (50 * (...) -1))) can be explained like that :
//50 = 50 keys by keyboard "page".
// clavier.currentFrame - 1 = modifier, tells which set of the 6000 glyphs
//needs to appear (and later, correspond with the codename from xml)
}
}
clavierUI.nextPage.addEventListener(MouseEvent.CLICK, fnNextPage);
function fnNextPage(e: Event): void {
clavierUI.nextFrame(); //no problem here, goes fast.
fnClavier(null);
}
clavierUI.prevPage.addEventListener(MouseEvent.CLICK, fnPrevPage);
function fnPrevPage(e: Event): void {
clavierUI.prevFrame(); //takes about 20secondes to go back.
fnClavier(null);
}
My code is probably far from being perfect (i'm still learning), but I don't know why it wouldn't work. Jumping around the frames and going to the next works perfectly, so anyone know why going back one frame takes forever?
Thank you.
You'd better use containers instead of frames. Frames get constructed and deconstructed each time you move between keyframes, while you con construct all the containers once and then display them as needed, one container at a time. I expect that Flash has optimization somewhere that constructs the next frame prior to it being shown via nextFrame() while an abrupt calling of prevFrame() forces Flash to construct it at once, and if it's very complex, it can take a lot of time.
You have 6000 glyphs? That's a lot, but not too much. You can create a set of containers, each holding 120 glyphs, for example. To do that, you create an array of Sprites, each having a grid of glyphs 12x10, there will be 50 of these. Then, when you need another page, display another sprite from the array. Also, if your glyph is a static vector object, you should convert it to vector graphics, and add as library item (Shape descendant, these eat less memory). If it's raster, use Bitmap and underlying BitmapData classes to use them.

How to change one object into another object?

This is mostly a question about code design. What you see here is a very condensed version of the original code.
An example of the code is:
player.rest();
This makes the player sleep.
I have other methods such as walk, run, talk etc. which all work great. The one that is a problem is polymorph. It changes the player from a human object to another object. The solution I came up with is this:
class main
{
var human:Human = new Human;
var alien:Alien = new Alien;
var cow:Cow = new Cow;
var player = human;
enterframe loop{
//other code
if (player does something)
player.polymorph = "alien";
switch (player.polymorph)
{
case "alien":
player = alien;
break;
case "cow":
player = cow;
break;
//etc
}
player.update();
}
}
I want something that looks like this:
class main
{
var human:Human = new Human;
var alien:Alien = new Alien;
var player = human;
enterframe loop
{
player.polymorph(alien);
}
}
I know my original solution is the wrong way to go about things as it encourages spaghetti code. How could I do it differently? I don't mind a whole rewrite, but need an example to help push me in the right direction. I hope this makes sense and thanks for the help.
If the second one can work, what would the polymorph function look like?
I thought of making a class called player and changing what that extends, but to my knowledge that can't be done? Plus I would like to change the character to something already in game rather than a new object.
One solution to your problem would be using a single class, in this case, your Player class, and a finite state machine. You'd have a Player class, which can be set to different states, such as HUMAN, ALIEN, COW, etc. When a polymorph event occurs you update the Player's state, perhaps by calling an initState() method, and handle the logic for being a human, alien, cow, accordingly in whatever method updates your player.
Assuming the player has an update() method it could contain the following:
switch (state) {
case ALIEN:
// do alien stuff
case COW:
// do cow stuff
case HUMAN:
// do human stuff
}
Next, instead of handling the various polymorph states in a switch statement, your Player class could have a polyMorph method that takes a state as a parameter:
public function polymorph(newState:Int) {
state = newState;
initState(state); // You could even just call the initState method instead, and completely omit the polymorph method
}
Using a finite state machine here would eliminate the need for numerous objects.

How can I give flash stage instances unique properties in Flash Professional to pass to AS3 script?

I've started building a rough game engine framework in Flash Professional and I'm curious how I can create objects in the Flash library that I'm able to drag onto the stage and assign properties that are accessible from AS3.
Example:
I want to create a switch object (e.g. a light switch), so that when the player interactes with it, it triggers something specific in code such as a light in the room turns on.
I understand that Flash has built in UI components that you can define properties within the Flash Professional environment (see image below), and I'm wondering if there's a way to create my own custom style components so that I can essentially have my level file open in flash (.fla) and then drag a switch component from my library, and type in some information such as what light it is controlling, and any other information I want.
(above is an example of the type of parameter control I'm looking for)
I've read a bit about extending the flash UIComponent class but I feel that that's not the right approach because it's overkill for what I want. All I want is to pass some basic parameters from a library stage instance into AS3. I do not want to pass data via the instance name because this seems very messy if I want to have more complex interaction.
Thanks!
I would create a "switch" movie clip and export it to actionscrip, same with a "light" movie clip. The in the main class .as file I would inset them into the stage, using addChild (clips) and then add a click listener to the "switch" movie clip to control the "light".
This can be easily done.
Component(s) are wrong approach in my opinion.
Firstly you would want to setup Actionscript linkage / label your Library item.
In Library Panel.
- Right Click on "yourMC" >> click "Properties".
- In Properties dialog Tick "Export for Action Script"
- Then Name your Class eg "yourMC_Class"
now MC is ready to be referenced in your code.
next you would want to Dynamically add your "yourMC" from library to stage.
which can be done like such.
// first reference library item
var yourMC_ref:yourMC_Class = new yourMC_Class();
// Then load dynamic mc item into var
var your_MC_OBJ = yourMC_ref;
// then add your MC to stage.
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
in a nutshell that's how I add library items to stage.
Obviously thats the basic function / code.
In a project I would have all code in an external class, in which case you would just set vars as public vars
public var yourMC_ref:yourMC_Class = new yourMC_Class();
public var your_MC_OBJ = yourMC_ref;
and the last 3 lines of code into a public function
public function ADD_First_MC()
{
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
}
Now 'your_MC_OBJ' can be used in more complex ways.
eg. to create a light switch there are many options depending on how you need to approch functionality.
eg. Apply a different MC library item to "your_MC_OBJ"
play specific frame within MCs.
However If it was me I would just use mouse function to switch light on or off using addChild removeChild.
eg.
public var LightON = 0;
public var yourMC_ref:yourMC_Class = new yourMC_Class();
public var your_MC_OBJ = yourMC_ref;
then create a public function that handles on / off events
public function LightON_OFF()
{
if(LightON == 1)
{
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
}
if(LightON == 0)
{
this.removeChild(your_MC_OBJ);
}
}
Hope this helps.
So, for what you want, while it may not be the best way to do what you want, I understand it's your experience you are constructing.
Use components, yes...in the following way (the most simple one):
Create a Movie Clip
Right-click it in library
Click on "Component Definitions"
Add a property, set a name, a variable name (var test, for this matter) and a default value
Click OK
Open your movie clip
Open code for the first frame and declare the variable without an initial value (var test:String;)
Trace it's value ( trace( test ); )
Go back to the stage root
Drag and drop the item from library to stage
Test it (Cmd/Ctrl + Enter) (maybe it will print null, dunno why, it ignores the default value sometimes)
Select your component on stage
Open the properties panel (Windows > Properties)
Go to Component Parameters on this panel and change the property value
You should see the value traced on console
And, I think, like this you can use properties from components for what you want, like using a String and getting the controlled mc by its name.
Good luck
I think what people are trying to say is that you can have the whole thing is data driven, and so you can combine the IDE with the data to come up with your final game.
But consider this ... it might be what you want.
If you have, for instance, a BaseSwitch Class:
public Class BaseSwitch extends MovieClip {
private var _lightName:String;
private var _light:Light;
public function get lightName():String {
return lightName;
}
public function set lightName(value:String):void {
if (value != _lightName) {
_lightnName = value;
//Note I don't advocate having children reach into their parents like this,
//but you sound like you don't want the parent involved in the process, so
//this is one way you could do it.
if (parent.hasOwnProperty(lightName) && parent[lightName] is Light) {
_light = parent[lightName];
} else {
trace('Could not find light', _lightName);
}
}
}
//other code to listen for gestures and operate the light
}
Now, when you want a switch to operate a specific light name, create a library instance and set its base class to BaseSwitch. When you close the dialog where you set the base Class, you'll notice that it gives you a dialogue that it couldn't find the Class in the Class path and one will be generated. You're going to replace it with a Class that sets the lightName. Create a new AS3 Class in the root directory with the same name as your library instance. It should look something like this:
public class SpecificSwitch {
public function SpecificSwitch() {
super();
lightName = 'theSwitch';
}
}
Other possible choices involve having the parent Class match up instances of switch with instances of light based on name, so if it finds a light1 and a light1Switch, it either gives a reference to the light to the switch or it simply sets up a mapping in its own event listening system.

I can't seem to access automatically named objects (instance##) placed on the stage in AS3, am I missing something?

I have a movieclip in the library that is added to the stage dynamically in the document class's actionscript. This movieclip contains many many child images that were imported directly from photoshop at their original positions (which must be preserved).
I do not want to manually name every single image instance, as there are dozens upon dozens.
I have already gone through and manually converted the images to symbols, as apparently flash won't recognize the "bitmap" objects as children of a parent movieclip in AS3 (numChildren doesn't see the bitmaps, but it sees the symbols).
I have an array filled with references to the dozens of children, and I loop through it, checking if each one is under the mouse when clicked. However, somehow, it is not detecting when I click over the items unless I manually name the child symbols (I tested by manually naming a few of them -- those ones became click-sensitive.)
I have already done trace() debugging all throughout the code, verifying that my array is full of data, that the data is, in fact, the names of the instances (automatically named, IE instance45, instance46, instance47, etc.), verifying that the function is running on click, verifying that the code works properly if I manually name the symbols.
Can any one see what's going wrong, or what aspect of flash I am failing to understand?
Here is the code:
//check each animal to see if it was clicked on
private function check_animal_hits():void
{
var i:int = 0;
var animal:Object = this.animal_container;
for (i=0; i<animal.mussels.length; i++)
{
if (this.instance_under_cursor(animal.mussels[i].name))
{
var animal_data = new Object();
animal_data.animal = "mussel";
this.send_data(animal_data);
}
}
}
Here is the code for the instance_under_cursor() method:
// Used for finding out if a certain instance is underneath the cursor the instance name is a string
private function instance_under_cursor(instance_name)
{
var i:Number;
var pt:Point = new Point(mouseX,mouseY);
var objects:Array = stage.getObjectsUnderPoint(pt);
var buttons:Array = new Array ;
var o:DisplayObject;
var myMovieClip:MovieClip;
// add items under mouseclick to an array
for (i = 0; i < objects.length; i++)
{
o = objects[i];
while (! o.parent is MovieClip)
{
o = o.parent;
}
myMovieClip = o.parent as MovieClip;
buttons.push(myMovieClip.name);
}
if (buttons.indexOf(instance_name) >= 0)
{
return true;
}
return false;
}
Update:
I believe I have narrowed it down to a problem with getObjectsUnderPoint() not detecting the objects unless they are named manually.
That is the most bizarre way to find objects under mouse pointer... There is a built-in function that does exactly that. But, that aside, you shouldn't probably rely on instance names as they are irrelevant / can be changed / kept solely for historical reasons. The code that makes use of this property is a subject to refactoring.
However, what you have observed might be this: when you put images on the scene in Flash CS, Flash will try to optimize it by reducing them all to a shape with a bitmap fill. Once you convert them to symbols, it won't be able to do it (as it assumes you want to use them later), but it will create Bitmpas instead - Bitmap is not an interactive object - i.e. it doesn't register mouse events - no point in adding it into what's returned from getObjectsUnderPoint(). Obviously, what you want to do, is to make them something interactive - like Sprite for example. Thus, your testing for parent being a MovieClip misses the point - as the parent needs not be MovieClip (could be Sprite or SimpleButton or Loader).
But, if you could explain what did you need the instance_under_cursor function for, there may be a better way to do what it was meant to do.

Rotate a sprite using ActionScript3

I want to rotate a sprite in 3d using AS3. The example below, tells how to do rotate an image using MXML and AS3, however, I want to do it through pure AS3:
Example
thanks
Flex is AS3. Flex compiles down to actionscript. Often, it's just a declarative (as opposed to the imperative) way to get things done.
So the meat of that example is in the code snippets:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
target.play();
}
}
//snip...
<fx:Declarations>
<fx:Number id="rotY">0</fx:Number>
<s:Rotate3D id="fxRotate3DNeg" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
<s:Rotate3D id="fxRotate3DPos" target="{image}" angleYTo="{rotY}"
autoCenterTransform="true" />
</fx:Declarations>
What's doing the work is the "Animate" object in conjunction with the two "Rotate3D" objects. So to get this to work in pure AS3, the only tough thing that's required is linking to the flex libraries. Depending on your IDE, that's pretty easy to do.
From there all you have to do is create the objects you want, imperatively instead of declaratively. So instead of doing things like:
<fx:Number id="rotY">0</fx:Number>
You need to do:
var rotY:Number = 0;
Once you know that, converting from Flex to AS3 and vice versa is pretty straightforward. The translated flex code would look something like the following in ActionScript:
import spark.effects.Rotate3D;
var rotY:Number;
var fxRotate3DNeg:Rotate3D;
var fxRotate3DPos:Rotate3D;
rotY = 0;
fxRotate3DNeg = new Rotate3D(image);; //the constructor sets the "target" property
fxRotate3DNeg.angleYTo = rotY;
fxRotate3DNeg.autoCenterTransform = true;
fxRotate3DPos = new Rotate3D(image);
fxRotate3DPos.angleYTo = rotY;
fxRotate3DPos.autoCenterTransform = true;
Now, that's off the top of my head, glancing at the Rotate3D API and typing in this text editor so I'm sure it's not perfect but it should give you a clear idea on how to move forward. If you need more help, let me know and I could translate more of the example.
I hope that helps,
--gMale
EDIT:
As I look at the code, one other tricky point is that the angleYTo properties are bound to rotY. So to truly get this to work, you have to explicitly set those properties in the playEffect function. As in:
private function playEffect(target:Animate, angle:Number):void {
if (!target.isPlaying) {
rotY += angle;
//manually set properties
fxRotate3DNeg.angleYTo = fxRotate3DPos.angleYTo = rotY;
target.play();
}
}
Alternatively, you could imperatively create the data binding, which is pretty easy to do. Then, the playEffect function would require no modification.
Its like rotating the object as you usually do. However in 3d space you will have to use:
sprite.rotationY
Make sure you are exporting for flash 10 or later since the 3d functionality doesnt exist in earlier versions.