optimizing a Flash swf with lots of movieclips - actionscript-3

I wrote an app that uses lots of sprites that are created at run-time. The app runs great on the PC, but I still would like to optimize it as best as I could. Here is an example of a function that creates these sprites. I am wondering if CachsAsBitmap is my solution, or if there is something else that I should consider trying. Thanks for any suggestions.
function createClips(){
for (var i:uint=0;i<100;i++){
c = new Sprite;
label_txt = new TextField;
bc.graphics.beginFill(colorOf, alphaOf);
bc.graphics.drawRect(label_x, label_y, labelWidth, labelHeight);
bc.graphics.endFill();
bc.mouseChildren = true;
bc.buttonMode = true;
label_txt.width = _width
label_txt.height = _height
label_txt.x = _x
label_txt.y = _y
label_txt.multiline = true;
label_txt.wordWrap = true;
label_txt.border = false;
}
}
Each of these sprites has an eventlistener that listens for certain things. Thse hold different values depending on what the user is doing. When the user selects a different screen, I remove them along with their eventlisteners via another function.
Thanks for any tips

Related

Swapping the image used for my character, to a seperate image on button click

So first off i'd like to state that i am not very good at AS3, i'm completely self taught so i am sure that there are many things i've done badly, inefficiently or plain wrong and i'm happy for any comments on these if there is things i can improve.
Okay so, this seems like a really simple problem but i don't know the exact code for it and i can't find an example anywhere
what i want to do is to change the image which i am using for my character to a separate image on a button click, then after a certain amount of time for him to go back to the original.
My image is set as a movie clip and i am calling it like so :
public var Smallclock_hero = new Smallclock;
it is worth noting that smallclock has it's own separate class.
is there a way that i can change this image on a mouse click event ?
A simple way would be:
Add a new image on the second frame of the Smallclock movieclip. Have this new image span several frames of the timeline for the duration you want it to appear for.
Place a stop(); action on the first frame of the Smallclock movieclip.
btn.addEventListener(MouseEvent.CLICK, btnChangeCharacterFrame);
function btnChangeCharacterFrame(e:MouseEvent)
{
Smallclock_hero.gotoAndPlay(2);
// Or use a frame label
// Smallclock_hero.gotoAndPlay("jump");
}
This can be achieved relatively simply using the visible property and setTimeout. When you click on your MovieClip you'll want to make the old image invisible and the new image visible:
oldImage.visible = false;
newImage.visible = true;
Then you'll want to use setTimeout to change the visible properties back to:
oldImage.visible = true;
newImage.visible = false;
setTimeout can run a function after a specified number of milliseconds. Here is an example of this technique on wonderfl : http://wonderfl.net/c/acxl
private var imageA:ImageA = new ImageA();
private var imageB:ImageB = new ImageB();
private var revertId:int;
public function Main() {
imageB.visible = false;
addChild(imageA);
addChild(imageB);
addEventListener(MouseEvent.CLICK, onClick);
}
private function onClick(e:MouseEvent):void{
clearTimeout(revertId);
revertId = setTimeout(revert, 1000);
imageB.visible = true;
imageA.visible = false;
}
private function revert():void{
imageB.visible = false;
imageA.visible = true;
}

Loading images using the URLRequest

recently started to learn ActionScript 3 and already have questions.
question remains the same: I'm uploading a picture using the object Loader.load (URLRequest). Loaded and displayed a picture normally. But it is impossible to read the values of attributes of the image height and width, instead issued zero. That is, do this:
var loader:Loader=new Loader();
var urlR:URLRequest=new URLRequest("Image.jpg");
public function main()
{
loader.load(urlR);
var h:Number = loader.height;// here instead of the width of the image of h is set to 0
// And if you do like this:
DrawText(loader.height.toString(10), 50, 50); // Function which draws the text as defined below
// 256 is displayed, as necessary
}
private function DrawText(text:String, x:int, y:int):void
{
var txt:TextField = new TextField();
txt.autoSize = TextFieldAutoSize.LEFT;
txt.background = true;
txt.border = true;
txt.backgroundColor = 0xff000000;
var tFor:TextFormat = new TextFormat();
tFor.font = "Charlemagne Std";
tFor.color = 0xff00ff00;
tFor.size = 20;
txt.x = x;
txt.y = y;
txt.text = text;
txt.setTextFormat(tFor);
addChild(txt);
}
Maybe attribute values must be obtained through the special features, but in the book K.Muka "ActionScript 3 for fash" says that it is necessary to do so. Please help me to solve this. Thanks in advance.
Well it's simple.
Flash is focused on the Internet, hence such problems.
If you wrote loader.load (urlR); it does not mean loaded. Accordingly, prior to the event confirming the end of loading, in loadare Null
if, instead of certain functions would be more code that would perhaps tripped your approach.
Yeah plus still highly dependent on the size of the file that you read.
Well, in general it all lyrics. Listen event on loader.contentLoaderInfo.addEventListener (Event.INIT, _onEvent), onEvent and read properties.
You need to wait for your image to load to be able to get values out of it.
Attach an eventListener to your URLLoader.
var urlR:URLRequest = new URLRequest("Image.jpg");
loader.load(urlR);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_complete);
function loader_complete(e:Event): void {
// Here you can get the height and width values etc.
var target_mc:Loader = evt.currentTarget.loader as Loader;
// target_mc.height , target_mc.width
}
Loader

AS3 - Tools that drag and rotate in flash TOOL MODE

I'm making an app/program that allows you to design your own piece of art with two basic functions by clicking the buttons on the UI, We'll call the 'Modes' for now.
Tweezer mode: you can drag the selected set of objects about in this mode.
Rotate Mode: this allows you to rotate a certain set of movie clips on the stage.
Assigning it.
I want it so that when rotate mode or tweezer mode is active the other is disenaged (enabled = false) or to that effect. I have arrived at a fork in the road where I need group them under method rotate or method tweezer. When tweezer is clicked, you move stuff about (only), and when rotate mode is selected you can rotate the movie clips...(only) this works fine until after you come away from rotate mode back tweezer that you can still rotate the movie clip! Could anyone shed some light on this so when I leave this mode you still can rotate it? Could any suggest the best way to organize this sort of functionality?
Thanks for your help - I'm an AS3 newbie.
// UI btns TOOLS ---------------------
spinny_mc.addEventListener(Event.ENTER_FRAME, fl_RotateContinuously);
function fl_RotateContinuously(event:Event)
{
spinny_mc.rotation += 20;
}
rotate_btn.visible = true;
tweezer_btn.visible = false;
//----- rotate tool
rotate_btn.addEventListener(MouseEvent.CLICK, spinmode);
function spinmode(event:MouseEvent):void
{
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,followspin);
function followspin(evt:MouseEvent)
{
spinny_mc.x = mouseX;
spinny_mc.y = mouseY;
rotate_btn.visible = false;
tweezer_cur.visible = false;
tweezer_btn.visible = true;
rotate_btn.enabled = true;
tweezer_btn.enabled = false;
skullface_mc.addEventListener(MouseEvent.CLICK, turnerbone);
function turnerbone(event:MouseEvent):void
{
skullface_mc.rotation+=45;
}
}
}
// ------------------------ tweeze tool
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,follow);
function follow(evt:MouseEvent){
tweezer_cur.x = mouseX;
tweezer_cur.y = mouseY;
}
tweezer_btn.addEventListener(MouseEvent.CLICK, tweezer);
function tweezer(event:MouseEvent):void
{
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,tweezer);
function tweezer(evt:MouseEvent){
tweezer_cur.x = mouseX;
tweezer_cur.y = mouseY;
rotate_btn.visible = true;
tweezer_cur.visible = true;
tweezer_btn.visible = false;
spinny_mc.visible = false;
rotate_btn.enabled = false;
tweezer_btn.enabled = true;
}
}
The problem comes down to your event listeners. They don't go away after you leave the function, as they are essentially objects in and of themselves. You need to do that manually.
At the top of the spinmode() function, add the line
stage.removeEventListener(MouseEvent.MOUSE_MOVE,tweezer);
At the top of the tweezer() function, add the line
stage.removeEventListener(MouseEvent.MOUSE_MOVE,followspin);
WARNING: I cannot rightly recall if this will throw an error if the event listener has not yet been created. If so, you can get around that using a Try/Catch, or an if-statement that links to a variable indicating what mode the user is in.
You may also need to rearrange your code a bit. I do not recommend nesting functions that affect the stage, as they can make life kinda difficult. Define the functions separately, and then call the other functions from the one you want.
Keep in mind, ActionScript is Object-Oriented, not procedural (and NOT strictly top-down). I'm not sure if you're coming from another language, but I know that took a lot of getting used to for me, coming from a procedural top-down technique.
WRONG
function myFunction1()
{
function myFunction 2()
{
//foobar
}
}
RIGHT
function myFunction1()
{
myFunction2();
}
function myFunction2()
{
//foobar
}

Something like cookies in Flash/ActionScript

i need to implement something like a cookie in a flash file....and i dont have a clue about ActionScript.
Basically it is a video with a mute/unmute button. If i mute the video and refresh the browser it is not muted again.So i need to persist the mute status somehow.
Here is my complete ActionScript File:
import flash.net.SharedObject;
var a:Boolean = false;
var cookie:SharedObject = sharedobject.getLocal("muted");
if (cookie.data.muted == true) {
SoundMixer.soundTransform = new SoundTransform(0);
Object(root).ton_btn.gotoAndStop(2);
}
ton_btn.addEventListener(MouseEvent.MOUSE_OVER, fl_MouseOverHandler);
function fl_MouseOverHandler(event:MouseEvent):void
{
Object(root).ton_btn.buttonMode = true;
Object(root).ton_btn.useHandCursor = true;
}
ton_btn.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
if (! a)
{
var muteStatus:Boolean = true;
cookie.data.muted = muteStatus;
SoundMixer.soundTransform = new SoundTransform(0);
Object(root).ton_btn.gotoAndStop(2);
trace(a);
}
else
{
var muteStatus:Boolean = false;
cookie.data.muted = muteStatus;
SoundMixer.soundTransform = new SoundTransform(1);
Object(root).ton_btn.gotoAndStop(1);
trace(a);
}
a = ! a;
}
This is not working, now my mute button is flickering....it seems, that the if clause is constantly executing.
Thanks for any tip, hint or link in advance. ;)
Regards
Nils
Edit:
So stupid...it was just a typo.
var cookie:SharedObject = sharedobject.getLocal("muted");
must be:
var cookie:SharedObject = SharedObject.getLocal("muted");
Now it is working.
I recommend following opensource that is popular ActionScript3.0 Cookie Frameworks. In general, two kinds of cookies in with the framework is known. Please see under open source. Solve your problem more quickly, you may give. Number 1 is a only Sourcode and Tutorial, Number 2 is a full of Frameworks.
Read and Write and Edit using a SharedObject
Actionscript3 Cookie Util

AS3 - make script wait for keystroke

I need my script to stop and wait until the 'enter' key is pressed, then continue, and if requirments are are not met, to go back and wait again.
its a login screen to a game i am working on, it needs to wait for the user to press enter, then check the provided credidentails and allow/deny them assces.
//log-in screen
loginframe = new Login_Frame();
addChild(loginframe);
LoginToServer();
function LoginToServer():Boolean
{
inputname = new TextField;
inputname.type = TextFieldType.INPUT;
inputname.border = true;
inputname.x = 200;
inputname.y = 200;
inputname.height = 35;
inputname.width = 545;
inputname.multiline = false;
inputname.text = "example";
loginframe.addChild(inputname);
inputpass = new TextField;
inputpass.type = TextFieldType.INPUT;
inputpass.border = true;
inputpass.x = 200;
inputpass.y = 300;
inputpass.height = 35;
inputpass.width = 545;
inputpass.multiline = false;
inputpass.text = "example";
loginframe.addChild(inputpass);
loginframe.addEventListener(KeyboardEvent.KEY_UP, hwndLogKeyboard);
while (!loginsucsess)
{
//do nothing *this halts the compiler, takes 30+ seconds for window to appear after execution*
//and causes the debugger to shut off (due to delay fault)
//so i have three problems
//1. this is clearly not an accepable way to do this
//2. this code dosnt work, without my debugger i cant fix it
//3. even if the code did work, this is a huge project, i cant be goin without my debugger
}
return true;
}
function hwndLogKeyboard(evt:KeyboardEvent):void
{
if (evt.keyCode == 13)
{
if ((inputname.text == "tyler") && (inputpass.text == "shadowcopy"))
loginsucsess = true;
}
}
I come from a C++ background where this solution would work just fine, but flash seems to have a problem with twidling its thumbs.
of course ive tryed asking Google, but the search results wernt anything even close to the required topic (me: AS3 wait for keypress - Google: Learn Flash OOP!) <-- no, bad Google.
thx in advance;
Tyler
Blocking UI is not optimal in any language, unless you're making a text console application.
Your implementation infinitely loops within your while() statement until max script execution timeout is reached.
Instead, use asynchronous design patterns:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0xefefef, frameRate = 60)]
public class LoginForm extends Sprite
{
protected var username:TextField;
protected var password:TextField;
public function LoginForm()
{
super();
// construct view
username = new TextField();
addChild(username);
password = new TextField();
addChild(password);
// listen for change events from the text fields
username.addEventListener(Event.CHANGE, loginChangeHandler);
password.addEventListener(Event.CHANGE, loginChangeHandler);
}
protected function loginChangeHandler(event:Event):void
{
if ((username.text == "tyler") &&
(password.text == "shadowcopy"))
{
// authentication verified - continue
}
}
}
}
When either of the text fields value changes, they are tested for the authentication credentials you have specified. If met, you can continue; otherwise, the application idles without any overhead.
Having a login button might be more inline with user experience.
Per debugging, from Flash Professional go to the "Debug" menu and select "Debug Movie".
From Flash Builder, right-click on the project application and "Debug as" or press the debug button from the toolbar. Built on Eclipse, you may find it more robust for code editing, debugging, and profiling.