Trigger a function on main timeline from a class? - actionscript-3

I am trying to trigger a function on the main timeline in my FLA from a class file. I can usually find the solution sifting through forum posts but all the ones i look at just aren't helping.
heres the code i have as of now, but it doesn't seem to be working.
//this is the code in my as3 class file
var e:Event = new Event("runFunc",true) dispatchEvent(e)
//here is the code in my .fla
addEventListener("runFunc", initialization);
I know using code in the FLA is a dirty method of coding but i am trying to add to a pre-existing game i had built previously.

A simple solution would be to migrate your code off the timeline with this method..
// class file
public function Main() {
//constructor
this.addFrameScript(1, frameOneFunc);
initialization();
}
private function frameOneFunc(){
This is essentially code in timeline for frame one.
}

i dont quite follow you glad, Are you saying to cut my code out of the fla and paste it in the frameOneFunc in the class file?
Here is a little more code to go off of.
.fla code(the function im trying to run)
function initialization();
{
//random code...
}
code in my class file
public function frame1()
{
this.savedstuff = SharedObject.getLocal("myStuff");
this.btnSave.addEventListener(MouseEvent.CLICK, this.SaveData);
this.btnLoad.addEventListener(MouseEvent.CLICK, this.LoadData);
if (this.savedstuff.size > 0)
{
//trying to trigger function here...this is my failed code below
//MovieClip(parent).initialization();
//var e:Event = new Event("runFunc",true)
//dispatchEvent(e)
//dispatchEvent(new Event("initialization"));
this.nameField.y = 800
this.note.y = 800
this.btnSave.y = 800
this.btnLoad.y = 800
this.tigger.y = 0;
trace(this.savedstuff.data.username);
this.nameField.text = this.savedstuff.data.username;
this.note.gotoAndStop(4);
}
return;
}

Related

Using Actionscript Worker to loop function to make it faster

My current code that allow application to upload data inside of Excel file into the AIR app is as follows;
import lib.xlsxreader.Worksheet;
import lib.xlsxreader.XLSXLoader;
public class Main extends MovieClip
{
private var fileGet: File = new File();
private var xloader: XLSXLoader = new XLSXLoader();
public function Main()
{
fileGet = File.applicationDirectory;
fileGet.addEventListener(Event.SELECT, selectExcel)
xloader.addEventListener(Event.COMPLETE, uploadComplete);
button.addEventListener(MouseEvent.CLICK, selectFile);
}
private function selectFile(e: MouseEvent): Void
{
fileGet.browseForOpen("Select File");
xloader.load(fileGet.nativePath);
}
private function uploadComplete(e: Event): Void
{
ws = xloader.worksheet("[Name of the worksheet]");
rowStart = 7;
rowEnd = ws.rows;
for (var i = rowStart; i <= rowEnd; i++)
{
//transferring data from excel into sqlite
}
}
}
The code above is not my complete code, I just shorten it to the relevant code. Let me know if you need more information.
Right now the code is transferring data from 30 columns and 1000++ rows from Excel file for about 10 minutes which is kinda slow and make the AIR app appear 'hang' or 'frooze' during uploading.
It come to my attention that I can use Worker API in Actionscript to fasten this process but for the life of me, I can't exactly figuring out how to restructuring my code to allow Worker API in my code.
I have read through example from here, here and here, but I still can't make heads or tails on this issue.
As far as my understanding goes, my code //transferring data from excel into sqlite should be included in class CountResult from this example...?
Can someone help me on this problem. Take note that I'm a self-learn amateur programmer trying to learn to make dekstop app using Adobe Animate.

How to access a variable from .as file in Flash?

I coded my game in AS3 and I added highscores to it. I am really new to AS3 so I wrote code in frames, but to add highscores I had to have some code in .as file. The problem is that scores take 2-3 seconds to load, and if I click on the menu button before they load game freezes, so I need to check if function for loading highscores has finished in .as file. There is such a function there
class getUserRankCallBack implements App42CallBack {
public function onSuccess(res: Object): void {
if (res is Game) {
var game: Game = Game(res);
for (var i: int = 0; i < game.getScoreList().length; i++) {
trace("user rank is : " + Score(game.getScoreList()[i]).getRank());
}
}
}
public function onException(excption: App42Exception): void {
trace("Exception is : " + excption);
}
}
so when it finishes I see the trace, but I can't seem to find what should I put in the if function to check if it's loaded in the frame code in the main .fla file... I tried making a new variable in .as file, like
var something:Number=1;
but if I try to trace something in the .fla it gives me access to undefined property, so I don't know how to do this and I think it's really simple.

want to change the code actionscript2 to actionscript3?

i am newbie to flash.i need to change the below actionscript code to actionscript 3.0 code.
i am currently working on drag and drop. so i want to duplicate the movieclip while dragging i found the code on internet but it is actionscript 2.0 so please convert it to as3. the box is a instance name of a movieclip.
the code blocks are:
var num:Number = 0
box.onPress = function(){
num++
duplicateMovieClip(box ,"box"+num, _root.getNextHighestDepth())
_root["box"+num].startDrag();
}
box.onReleaseOutside = function(){
trace(_root["box"+num])
stopDrag();
}
If you dont want to use seperate .as file, follow this steps:
1- assign AS linkage to box movieClip (in library panel):
2- Select frame 1 on the timeline, and paste this code in the Actions panel:
var boxes:Array=[];
//var box:Box=new Box();
//addChild(box);
box.addEventListener(MouseEvent.MOUSE_DOWN,generateBox);
function generateBox(e:MouseEvent):void{
var newBox:Box=new Box();
newBox.x = e.target.x;
newBox.y = e.target.y;
newBox.startDrag();
newBox.addEventListener(MouseEvent.MOUSE_UP,stopD);
newBox.addEventListener(MouseEvent.MOUSE_DOWN,startD);
boxes.push(newBox);
addChild(newBox);
}
function startD(e:MouseEvent):void{
e.target.startDrag();
}
function stopD(e:MouseEvent):void{
e.target.stopDrag();
}
Unfortunately, there's no duplicateMovieClip analog in AS3, so you'll have to create a Class for your box movieClip template. Let's say it will be called BoxTemplate. (You can google how to create Classes for your library object). Add a Class with this name and add this code (event subscription in the constructor and a private event listener). You'll get something like this:
package
{
public class BoxTemplate
{
public function BoxTemplate()
{
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
private function onMouseUp(e:MouseEvent):void
{
stopDrag();
}
}
Leave your present instance of this symbol on the stage. This is your code in the frame:
import flash.event.MouseEvent
box.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void
{
var newBox:BoxTemplate = new BoxTemplate();
newBox.x = e.target.x;
newBox.y = e.target.y;
addChild(newBox);
newBox.startDrag();
}
It will allow you to infinitely clone your boxes. Of course, you can add all of them in the array to keep the references.

CS5+AS3 Preloader starts at 50%; no clue why

I know there are a lot of previous topics about preloaders and I've tried to follow every one of them but I still get the same problem (well they have helped me go from 80% -> 50%)
Right now it starts at 61450 / 125207 which is about 50%.
Here is my Main Document (default class file for the entire project) class:
public class MainDocument extends MovieClip
{
private var preloader:Preloader;
private var sB:startButton;
public function MainDocument()
{
preloader = new Preloader();
preloader.x = 300;
preloader.y = 400;
addChild(preloader);
loaderInfo.addEventListener(Event.COMPLETE,addStartButton,false,0,true);
}
private function addStartButton(e:Event):void
{
sB = new startButton();
sB.x = 300;
sB.y = 450;
sB.addEventListener(MouseEvent.CLICK,sMainMenu,false,0,true);
addChild(sB);
loaderInfo.removeEventListener(Event.COMPLETE,addStartButton);
}
private function sMainMenu(e:Event):void
{
sB.removeEventListener(MouseEvent.CLICK,sMainMenu);
removeChild(sB);
removeChild(preloader);
sB = null;
preloader = null;
var menuScreen = new MenuScreen();
addChild(menuScreen);
//I have heard that the following code might work better:
//var menuScreen:Class = getDefinitionByName("MenuScreen") as Class;
//addChild(new menuScreen() as DisplayObject);
}
}
And the Preloader that it attaches:
public class Preloader extends MovieClip
{
public function Preloader()
{
addEventListener(Event.ENTER_FRAME,Load);
}
private function Load(e:Event):void
{
//"bar" is a movieclip inside the preloader object
bar.scaleX = loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
//"percent" is a dynamic text inside the preloader object
percent.text = Math.floor(loaderInfo.bytesLoaded/loaderInfo.bytesTotal*100)+"%";
trace(loaderInfo.bytesLoaded+" / "+loaderInfo.bytesTotal);
if (loaderInfo.bytesLoaded == loaderInfo.bytesTotal)
{
removeEventListener(Event.ENTER_FRAME,Load);
}
}
}
-> Nothing is set to Export on Frame 1 except for the Preloader
-> No objects exist on the first frame; the only code on first frame is stop();
-> I placed a copy of every single MovieClip in the second frame and when the startButton is clicked, a gotoAndStop(3); is run so no one ever sees frame 2.
If anyone knows of anything simple that I could have forgotten, please let me know!
Thanks!
You're tying to use a preloader in the file being preloaded. In that case, there is going to be bloat from the rest of the project's code and assets. The reason you are seeing your preloader seemingly delayed is because a swf must load completely before any code will execute. This includes all assets on stage regardless of what frame they are on, even if you have settings in place to export on something other than frame 1. Instead, try using a blank shell as your preloader. This shell will have nothing in it but the loader code and a preloader graphic or animation. When the load is finished, hide your preloader and add your loaded content to the stage of the shell, or a container movieclip in the shell.
All the following code goes in your shell, which is just another FLA file with nothing in it but this code, and a preloader bar. The dimensions of this file should be the same as the file you are loading into it, ie your original swf file you were trying to preload.
Use it by calling loadSwf( "mySwfNameOrURLToSwf.swf" );
The variable _percent will populate with the current load percentage, which you can correspond to your loading bar scale. Presuming the preloader bar is named "bar", the line bar.visible = false; in the onSwfLoaded function will hide it. addChild( _swf ) adds the loaded swf to the shell's stage. The line _swf.init(); references a function in the loaded swf you will need to add called init() that starts your loaded swf doing whatever it is its supposed to do. Have everything in the loaded swf start on the first frame now, including the init() function.
import flash.display.MovieClip;
import flash.display.DisplayObject;
import flash.display.Loader;
import flash.display.Bitmap;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.SecurityDomain;
import flash.system.LoaderContext;
import flash.system.Security;
import flash.events.Event;
import flash.events.ProgressEvent;
var _swfLoader:Loader;
var _swf:DisplayObject;
var _percent:Number;
function loadSwf( swfURL:String ):void
{
_swfLoader = new Loader();
var req:URLRequest = new URLRequest( swfURL );
var loaderContext:LoaderContext = new LoaderContext();
loaderContext.applicationDomain = ApplicationDomain.currentDomain;
loaderContext.checkPolicyFile = true;
_swfLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onSwfProgress);
_swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSwfLoaded);
_swfLoader.load(req, loaderContext);
}
function onSwfProgress( evt:Event ):void
{
_percent = Math.round( ( evt.target.bytesLoaded / evt.target.bytesTotal ) * 100 );
}
function onSwfLoaded( evt:Event ):void
{
_swfLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onSwfProgress);
_swfLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onSwfLoaded);
_swf = _swfLoader.content;
addChild( _swf );
bar.visible = false;
_swf.init();
_swfLoader = null;
}
your code looks ok.
when you are not on a http server, loading process are simulated.
After compiling, press crtl + B.
In menu you can choose the downloading speed and simulate a download by pressing again ctrl+enter.
it might help you to debug your preloader
#Lee Burrows What you said was right but would have been better if you looked at what I mentioned at the end of the code (three bold points)
The solution I used was:
-> I set everything to Export on Frame 2 on my 3 frame document.
-> Removed everything on Frame 2
-> Created a TextField via constructor and used drawRectangle for loading bar
-> No movieclips present on frame 1, and used
var menuScreen:Class = getDefinitionByName("MenuScreen") as Class;
addChild(new menuScreen() as DisplayObject);
instead of the previous code.
The reason why what I had originally didn't work because, as Lee Burrows mentioned, the Export for Actionscript hangs the loading if X = 1 in Export on Frame X, regardless if Export on Frame 1 was checked or not. Changing it to 2 or unchecking Export for Actionscript were the two solutions (except if it isn't exported for actionscript, then its code cant be referenced to).
Preloader starts at about 2% now.

preloading external .swf with class file as3

so i'm trying to make an external preloader to load my main .swf (loading.swf) file that has a class file named mainLoading.as using this code:
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("loading.swf"));
var loadingPage:loading = new loading;
function loop (e:ProgressEvent):void{
addChild(loadingPage);
loadingPage.x = stage.stageWidth/2;
loadingPage.y = stage.stageHeight/2;
}
function done (e:Event):void{
removeChild(loadingPage);
addChild(l);
}
so I'm getting an error message saying:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at mainLoading()
I think i'm getting the error message because i am accessing the stage in my mainLoading() class file. I tried adding this to the constructor in my class file but it didn't work:
public function mainLoading () {
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event): void {
initStartUpScene ();
}
my initStartUpScene function just throws the intro scene to the loading.swf
any suggestions?
thanks for your help.
(question) is your mainLoading extends either Sprite or Movieclip ?
EDIT
After reading your comment, I would suggest trying this :
Add a function call inside the swf content in your complete progress handler :
function done (e:Event):void{
removeChild(loadingPage);
addChild(l);
Object(l.content).initMethod();
}
content let you access the methods in your loaded .swf main class (e.g. mainLoading)
And replace the event handling in your mainLoading by :
public function mainLoading () {
//no event handling in constructor
}
public function initMethod():void {
//here you go
init();
}
public function init():void { ... //No more event here
Btw it's not the cleanest way to solve your problem.
If that's the exact message you are getting, then yes, adding the ADDED_TO_STAGE listener should have fixed it. Remember to recompile the "loading.swf" if you make any changes to it (a step I always seem to forget)
Does "loading.swf" run just fine without any errors when running it on it's own (not loading it into the "container" SWF)?
This may be unrelated to the question you asked, but you might get better results and avoid some errors by structuring your code like this:
var loadingPage:loading = new loading;
addChild(loadingPage);
loadingPage.x = stage.stageWidth/2;
loadingPage.y = stage.stageHeight/2;
var l:Loader = new Loader();
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
l.load(new URLRequest("loading.swf"));
//I renamed this function since I believe "loop" is a reserved keyword.
function onProgress (e:ProgressEvent):void{
//No code needed
}
function onComplete (e:Event):void{
removeChild(loadingPage);
addChild(l);
}
You can remove the "onProgress" function if you won't be needing it as well.
OOOOOOKKKKK, so after about a week of admitting defeat, trying it again, rewriting almost half of my code, trying to convince myself that preloaders are overrated, i finally figured it out (drum roll please):
I had a variable that was referencing the stage being called before my constructor method was called. like this:
private var xScrollPosRight:Number = stage.stageWidth - xScrollPosLeft;
I just changed stage.stageWidth to 750 and it worked.
live and learn.