Loading more than one child image AS3 - actionscript-3

I'm trying to load 2 images in to my flash file but getting an error - new to this AS3 malarkey any help would be appreciated!
Getting error: 5 1151: A conflict exists with definition request in namespace internal.
var myImage:String = dynamicContent.Profile[0].propImage.Url;
var myImage2:String = dynamicContent.Profile[0].prop2Image.Url;
var myImageLoader:StudioLoader = new StudioLoader();
var request:URLRequest = new URLRequest(enabler.getUrl(myImage));
myImageLoader.load(request);
myImageLoader.x =17;
myImageLoader.y = 0;
var myImageLoader2:StudioLoader = new StudioLoader();
var request:URLRequest = new URLRequest(enabler.getUrl(myImage2));
myImageLoader.load(request);
myImageLoader.x =17;
myImageLoader.y = 0;
if(this.currentFrame == 1) {
addChildAt(myImageLoader, 2);
}
if(this.currentFrame == 2) {
addChildAt(myImageLoader2, 2);
}

It's usually a good idea to move duplicate code into its own function instead of doing copy + paste:
function loadImage(file:String, x:Number, y:Number):StudioLoader{
var myImageLoader:StudioLoader = new StudioLoader();
var request:URLRequest = new URLRequest(file);
myImageLoader.load(request);
myImageLoader.x = x;
myImageLoader.y = y;
return myImageLoader;
}
addChild(loadImage(enabler.getUrl(myImage1),17,0));
addChild(loadImage(enabler.getUrl(myImage2),17,0));
That's not just giving you better structured code but also fixes your duplicate variable definition issue because what's defined locally inside a function stays inside the function.
This might provide some insight:
http://www.adobe.com/devnet/actionscript/learning/as3-fundamentals/functions.html

You can't create a new variable with the same name as an existing one, in your case I'm speaking about your URLRequest request, so to avoid this type of error you can do like this :
var myImageLoader2:StudioLoader = new StudioLoader();
// assing a new URLRequest to an existing var
request = new URLRequest(enabler.getUrl(myImage2));
// here you want use the myImageLoader2, not myImageLoader
myImageLoader2.load(request);
myImageLoader2.x =17;
myImageLoader2.y = 0;
Or :
var myImageLoader2:StudioLoader = new StudioLoader();
// create a new URLRequest var, so the name should be different
var request2:URLRequest = new URLRequest(enabler.getUrl(myImage2));
// here you want use the myImageLoader2, not myImageLoader
myImageLoader2.load(request2);
myImageLoader2.x =17;
myImageLoader2.y = 0;

Additionally, I notice in the second block that you declare myImageLoader2 but you then use the original myImageLoader to do the load request. So even if you do declare a new URLRequest, you wont get both images loaded.
Akmozo's solution has this corrected.

Related

Calling a variable from outside of a function

I'm so stumped. I'm hoping someone can help me out here! I'm trying to call the variable named "time" from outside of a function.
Here is my code:
var myXML:XML = new XML();
var XML_URL:String = "time.xml";
var myXMLURL:URLRequest = new URLRequest(XML_URL);
var myLoader:URLLoader = new URLLoader(myXMLURL);
myLoader.addEventListener(Event.COMPLETE, xmlLoaded);
var time;
function xmlLoaded(event:Event):void
{
time = XML(myLoader.data);
}
trace(time);
Here is what my XML looks like
<time>10</time>
Every time I run the trace(time); outside of the function - I get an "undefined" message in the output window.
How can I access the variable "time" from outside of my function so I can assign it to another variable like this:
var VIDEOS_SECONDS = time;
Thank you so much for any help!
Timothy
Most of it looks correct, the issue is the xml file is loading asynchronously and you expect it to load synchronously.
If you move trace(time) right after time = XML(myLoader.data); you should see the expected value. You can call another function from that COMPLETE handler to setup the rest of your code that relies on data being loaded first:
var myXML:XML = new XML();
var XML_URL:String = "time.xml";
var myXMLURL:URLRequest = new URLRequest(XML_URL);
var myLoader:URLLoader = new URLLoader(myXMLURL);
myLoader.addEventListener(Event.COMPLETE, xmlLoaded);
var time;
function xmlLoaded(event:Event):void
{
time = XML(myLoader.data);
trace(time,new Date());
//time is ready here
}
//although time is global, xml hasn't loaded at this point yet, check timestamps
trace(time,new Date());

Why does (myMC.myArray = myOtherMC.myOtherArray;) cause any changes to myMC.myArray to also change myOtherMC.myOtherArray?

var myArray:Array = new Array();
var myMC:MovieClip = new MovieClip();
myMC.myArray = myArray;
trace(myMC.myArray[10]); //Output: undefined
var newMC:MovieClip = new MovieClip();
newMC.myOtherArray = myMC.myArray;
newMC.myOtherArray[10] = [];
newMC.myOtherArray[10][0] = 100;
trace(myMC.myArray[10]); //Output: 100
Why does that happen, and is there any way to avoid it?
EDIT:
Found a function that can clone associative arrays here.
Here is the function (from the above link):
function clone(source:Object):*
{
var myBA:ByteArray = new ByteArray();
myBA.writeObject(source);
myBA.position = 0;
return(myBA.readObject());
}
Does making the function return type "*" mean that it can be any type? or is it something specific to objects/arrays?
It's because you have passed a reference of the original array to the new clip. Arrays, as objects, are not primitives and therefore will always be referenced.
If you would like to clone an array, keeping the original intact, use this method:
var b:Array = a.concat();
b will be a new array. a can modified without changing b.

Running-order of nested function-calls delayed/altered due to URLloader in AS3?

First of all: English is not my first language. ;-)
I am compiling the following code:
var sqldata:String;
function sql(saveorload,sqlstring) {
var sqlloader = new URLLoader();
var sqlrequest = new URLRequest("http://***/sql.php");
sqlrequest.method = URLRequestMethod.POST;
sqlloader.addEventListener(Event.COMPLETE, sqldonetrace);
var variables:URLVariables = new URLVariables();
variables.sqlm = saveorload;
variables.sqlq = sqlstring;
sqlrequest.data = variables;
sqlloader.load(sqlrequest);
}
function sqldonetrace(e:Event) {
sqldata = e.target.data;
}
sql("1","SELECT * FROM songs WHERE `flag2` LIKE '0'");
trace (sqldata);
So, here comes the problem:
"sqldata" is traced as "null". AS3 seems to run "sql", then "trace" and then "sqldone", but i would need sql -> sqldone -> trace...
I can't put the trace-command in the sqldone-function because it is stored as *.as and loaded at different points in my .swf and not always followed by only a trace-command.
Any Ideas/hints/flaws in script?
Actionscript is, by design, an event driven language. It also guarantees that the code executes in a single thread i.e. if a function call starts, no other(new call) actionscript code would execute until the first call finishes.
That being said, what you should have is to pass a complete handler to sql(...).
function sql(saveorload:String, sqlstring:String, completeHandler:Function):void
{
var sqlloader = new URLLoader();
var sqlrequest = new URLRequest("http://***/sql.php");
sqlrequest.method = URLRequestMethod.POST;
sqlloader.addEventListener(Event.COMPLETE, completeHandler);//tell urlloader to use the complete handler passed in parameters
var variables:URLVariables = new URLVariables();
variables.sqlm = saveorload;
variables.sqlq = sqlstring;
sqlrequest.data = variables;
sqlloader.load(sqlrequest);
}
And then use it from some other place like:
sql("1","SELECT * FROM songs WHERE `flag2` LIKE '0'", sqldonetrace);
function sqldonetrace(e:Event)
{
var sqldata:String = e.target.data;
trace (sqldata);
}
Also, I think you should check for error events from urlloader. Pass another parameter to sql as errorHandler

JPEGencode issue in as3

Here is my code. What I m trying to achieve is to be able to capture an image from the the camera and upload it onto a media server but so far I have not been able to encode it succesfully .Can someone please point me in the right direction.
Here is the code
var imagePromise:MediaPromise = event.data;
imageLoader = new Loader();
imageLoader.contentLoaderInfo.addEventListener( Event.COMPLETE, asyncImageLoaded );
imageLoader.addEventListener( IOErrorEvent.IO_ERROR, cameraError );
imageLoader.loadFilePromise( imagePromise );
function asyncImageLoaded(event:Event):void
{
var destination:String = "upload.php";
var now:Date = new Date();
var fileName = "IMG" + now.fullYear + now.month + ".jpg";
var image:Bitmap = Bitmap(imageLoader.content);
var bitmapData:BitmapData = image.bitmapData;
var j = new JPGEncoder(80);
var bytes:ByteArray = j.encode(bitmapData);
}
This is the error I get when i try to encode the image
TypeError: Error #1009: Cannot access a property or method of a null object reference.
which line? 1009 means you're trying to access a variable of something that is NULL. I'm guessing in this case, it's probably the line:
var image:Bitmap = Bitmap(imageLoader.content);
Try adding this:
if (imageLoader.content is Bitmap) {
var image:Bitmap = Bitmap(imageLoader.content);
} else {
throw new Error("What the heck bob?");
}
If it's an error, I bet the content was not decoded properly (which could mean a mime-type that wasn't image/jpg)
Additionally, you could probably use the native jpeg encoder for speed: (flash 11 i believe?)
var byteArray:ByteArray = new ByteArray();
bitmapData.encode(new Rectangle(0,0,640,480), new flash.display.JPEGEncoderOptions(), byteArray);
http://help.adobe.com/en_US/as3/dev/WS4768145595f94108-17913eb4136eaab51c7-8000.html

Unloading a Loader with actionscript 3

Hello and thank you very much for looking at this. I've spent too many hours struggling.
The code below loads a slideshow of four images, along with thumbnails for those images. It works fine.
I've added a button called "invis_button", that when pressed is supposed to remove the 3 loaders that make up the slideshow, using the removeChild command for each loader.
But this is the problem, there are 3 loaders involved in the slide-show. The removeChild command successfully removes one of the loaders (named "loader3"), but not the other two ("container3", and "thumbLoader3"). It returns an error stating "access of undefined property thumbLoader3" or "Container3".
Can someone tell me why this is ? Or better still, how to make that button (invis_button) unload the entire slide-show.
var images3:Array = ["ad_bona1.jpg", "ad_bona2.jpg", "ad_darkhawk1.jpg", "ad_darkhawk2.jpg"];
var thumbX3:Number = -375;
var thumbY3:Number = 220;
var loader3:Loader = new Loader();
loader3.load(new URLRequest("assets/ad_bona1.jpg"));
addChild(loader3);
loader3.alpha = 0;
loadThumbs3();
function loadThumbs3():void
{
var thumbLoader3:Loader;
var container3:Sprite = new Sprite();
addChild(container3);
container3.buttonMode = true;
for(var i3:uint = 0; i3 < images3.length; i3++)
{
thumbLoader3 = new Loader();
thumbLoader3.load(new URLRequest("assets/thumbs/" + images3[i3]));
thumbLoader3.x = thumbX3;
thumbLoader3.y = thumbY3;
thumbX3 += 85;
container3.addChild(thumbLoader3);
thumbLoader3.addEventListener(MouseEvent.CLICK, thumbClicked3);
}
}
function thumbClicked3(event:MouseEvent):void
{
var path3:String = event.currentTarget.contentLoaderInfo.url;
path3 = path3.substr(path3.lastIndexOf("/") + 1);
loader3.load(new URLRequest("assets/" + path3));
}
///PROBLEM BELOW, button removes only "loader3" and not the other two for some reason
invis_button.addEventListener(MouseEvent.CLICK, unload_loaders);
function unload_loaders(event:MouseEvent):void{
removeChild(loader3);
removeChild(thumbLoader3);
removeChild(container3);
}
Not sure if this is the entire reason behind what you're observing... but for starters, "thumbloader3" and "container3" are scoped locally to the loadThumbs3() method, which means once you finish executing the function, Flash's handles to those objects are lost (not to mention being in an entirely different scope)... try creating class-level properties for those two. Once that's done you should be able to successfully remove them from the stage later on.
I hope that you're also properly destroying your objects, and for the sake of brevity you just chose to omit that code above.
I've edited the code you had above & put the properties into the proper scope. (the multiple copies of thumbLoader3 are now collected inside of a vector (specialized array) so that they can be properly addressed when it comes time to destroy them)
I also wrote you a proper destroy method. ;)
I haven't tried it on my own machine, but give it a spin & see how it goes.
var images3:Array = ["ad_bona1.jpg", "ad_bona2.jpg", "ad_darkhawk1.jpg", "ad_darkhawk2.jpg"];
var thumbX3:Number = -375;
var thumbY3:Number = 220;
// begin new instance properties..
// created a new property, allowing you to group (and hold on to) the multiple thumbLoaders
var thumbLoader3Vector:Vector.<Loader> = new Vector.<Loader>();
var container3:Sprite;
// end new instance properties
var loader3:Loader = new Loader();
loader3.load(new URLRequest("assets/ad_bona1.jpg"));
addChild(loader3);
loader3.alpha = 0;
loadThumbs3();
function loadThumbs3():void
{
// this is where container3 used to be declared
container3 = new Sprite();
addChild(container3);
container3.buttonMode = true;
for(var i3:uint = 0; i3 < images3.length; i3++)
{
var tPtr:int = thumbLoader3Vector.length;
thumbLoader3Vector.push(new Loader());
// this is where thumbLoader3 used to be declared & instantiated
thumbLoader3Vector[tPtr].load(new URLRequest("assets/thumbs/" + images3[i3]));
thumbLoader3Vector[tPtr].x = thumbX3;
thumbLoader3Vector[tPtr].y = thumbY3;
thumbX3 += 85;
container3.addChild(thumbLoader3Vector[tPtr]);
thumbLoader3Vector[tPtr].addEventListener(MouseEvent.CLICK, thumbClicked3);
}
}
function thumbClicked3(event:MouseEvent):void
{
var path3:String = event.currentTarget.contentLoaderInfo.url;
path3 = path3.substr(path3.lastIndexOf("/") + 1);
loader3.load(new URLRequest("assets/" + path3));
}
///PROBLEM BELOW, button removes only "loader3" and not the other two for some reason
invis_button.addEventListener(MouseEvent.CLICK, unload_loaders);
function unload_loaders(event:MouseEvent):void{
// since the thumbLoader3 Loaders are children of container3 in the display list, we need to remove them first
for(var $i:uint = 0;$i<thumbLoader3Vector.length;$i++)
{
removeChild(thumbLoader3Vector[$i]);
// also make sure you remove the listener, so that the object will be picked up by garbage collection
thumbLoader3Vector[$i].removeEventListener(MouseEvent.CLICK, thumbClicked3);
}
// and then just set the entire vector to null
thumbLoader3Vector = null;
// remove the loader3 object & set it to null
removeChild(loader3);
loader3 = null;
// remove the container3 object & set it to null
removeChild(container3);
container3 = null;
}