The right way to send variables with as3 to asp? - actionscript-3

Im trying to make an swf send a phone-number to a specific asp-fil on the press of a button.
But since I'm an as3 rookie I have no idea where this code is going wrong (PLEASE HELP):
import flash.events.IOErrorEvent;
import flash.display.*;
import flash.events.MouseEvent;
import flash.net.*;
import flash.events.Event;
public class action extends MovieClip
{
private var swf_front_mc:swf_front = new swf_front ;
var request:URLRequest = new URLRequest("succes.html");
var request2:URLRequest = new URLRequest("http://www.example.com");
public var mobilNr:Number = new Number(swf_front_mc.mobilInput.text);
public var varsToSend:URLVariables = new URLVariables();
public function action()
{
addChild(swf_front_mc);
swf_front_mc.name = "swf_front_mc";
swf_front_mc.x = 0;
swf_front_mc.y = 0;
makeInteraction();
}
private function makeInteraction():void
{
swf_front_mc.submit_mc.addEventListener(MouseEvent.CLICK, submitForm);
}
function submitForm(e:MouseEvent):void
{
//trace("hello");
varsToSend.RecipientMobileNumber = mobilNr;
// Create URL Request, set to POST, and attach data
var formRequest:URLRequest = new URLRequest("webform_input.asp");
formRequest.method = URLRequestMethod.GET;
formRequest.data = varsToSend;
// Create URL Loader, attach listeners, and load URL Request
var varLoader:URLLoader = new URLLoader ;
varLoader.addEventListener(Event.COMPLETE, onLoaded);
varLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
varLoader.load(formRequest);
}
function onLoaded(e:Event):void
{
navigateToURL(request,"blank");
}
function ioErrorHandler(e:IOErrorEvent):void
{
navigateToURL(request2,"blank");
}
}

Thanks for the tips and hints guys...
Meanwhile i got the perfect solution from a friend. It's much shorter and more simple then I thought possible. Here it is:
package app.form
{
import flash.net.*;
import flash.display.*;
import flash.events.*;
public class container extends MovieClip
{
public function container()
{
sendBtn.addEventListener(MouseEvent.CLICK, sendBtnClick);
}
public function SendToURLExample(_navn:String, _tlf:String) {
var url:String = "http://www.yourdomain.com/file.asp";
var variables:URLVariables = new URLVariables();
variables.name = _name;
variables.phone = _phone;
var request:URLRequest = new URLRequest(url);
request.data = variables;
trace("sendToURL: " + request.url + "?" + request.data);
try {
sendToURL(request);
}
catch (e:Error) {
// handle error here
}
}
// two text-example-fields on stage called input_text_name/input_text_mobil
private function sendBtnClick(e:MouseEvent):void {
SendToURLExample(input_text_name.text, input_text_mobil.text);
}
}
}
Hope this will solve the something for someone out there :)

try this one example
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/net/URLVariables.html#includeExamplesSummary
or you can try to encode your vat into GET URL like new URLRequest("localhost/?number="+numberField.text);
but first one try navigatetourl method from previous sample.
p.s. look at this too: http://blog.flexexamples.com/2007/08/16/using-httpservice-tag-to-sendreceive-variables-to-a-server-side-script/

Related

AS3 Call to possibly undefined method with a static type Class error i can't fix

i am following a game tutorial but making some modifications. to add multiple levels i added instance's but this screwed up more then i can fix.
every level points can be made and if you die those points should be seen on the gameoverscreen.
the level code
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
import flash.media.SoundMixer;
import flash.media.Sound;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.net.URLLoader;
public class LevelEen extends MovieClip
{
public var gerardJoling : GerardJoling;
public var geerTimer:Timer;
public var geerGame : GeerGame;
public var geer_score:GeerScore;
public static var instance:LevelEen;
public var gameOverScherm:GameOverScherm;
public var levelEen:LevelEen;
public var pattys:Array;
public var enemy:VrouwVijand;
public var volumeAdjust:SoundTransform = new SoundTransform();
public var channelNogniet:SoundChannel = new SoundChannel();
public var channelScore:SoundChannel = new SoundChannel();
public var Nogniet:URLRequest = new URLRequest("Sounds/Gerard Joling - Het is nog niet voorbij.mp3");
public var Score:URLRequest = new URLRequest("Sounds/10046_1361186725.mp3");
public var noMoreNogniet:Sound = new Sound(Nogniet);
public var noMoreScore:Sound = new Sound(Score);
public function LevelEen()
{
SoundMixer.stopAll();
volumeAdjust.volume = 1;
channelNogniet = noMoreNogniet.play(0,10);
channelNogniet.soundTransform = volumeAdjust;
gerardJoling = new GerardJoling();
addChild(gerardJoling);
gerardJoling.x = mouseX;
gerardJoling.y = mouseY;
pattys = new Array();
geerTimer = new Timer( 25 );
geerTimer.addEventListener( TimerEvent.TIMER, geerInteractie);
geerTimer.start();
}
public function geerInteractie( timerEvent:TimerEvent ):void
{
if ( Math.random() < 0.04 )
{
var randomX:Number = Math.random() * 550;
var vrouwVijand:VrouwVijand = new VrouwVijand( randomX, -40 );
pattys.push(vrouwVijand);
addChild(vrouwVijand);
geer_score.addToValue( 0 );
}
gerardJoling.x = mouseX;
gerardJoling.y = mouseY;
var i:int = pattys.length - 1;
var enemy:VrouwVijand;
var finalScore:Number = getFinalScore();
while ( i > -1 )
{
enemy = pattys[i];
enemy.dalen();
if ( gerardJoling.hitTestObject(enemy) )
{
geerTimer.stop();
SoundMixer.stopAll();
GameOverScherm.setFinalScore( finalScore );
GeerGame.instance.switchScreen( "GameOverScherm" );
trace (geer_score.currentValue);
}
if ( enemy.y > 400 )
{
removeChild( enemy );
pattys.splice( i, 1 );
geer_score.addToValue( 10 );
channelScore = noMoreScore.play(0,1);
}
if (geer_score.currentValue > 40)
{
geerTimer.removeEventListener(TimerEvent.TIMER, geerInteractie);
GeerGame.instance.switchScreen( "LevelTwee" );
}
i = i - 1;
}
}
public function getFinalScore():Number
{
return geer_score.currentValue;
}
}}
here a score is calculated in a other class, but the setFinalScore en getFinalscore also have to do there job to get the final score and send it to the gameoverscherm
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.text.TextField;
import flash.media.Sound;
import flash.media.SoundTransform;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import flash.net.URLLoader;
import flash.media.SoundMixer;
public class GameOverScherm extends MovieClip
{
public var gameOverScherm:GameOverScherm;
public var levelEen:LevelEen;
public var volumeAdjust:SoundTransform = new SoundTransform();
public var channelGeer:SoundChannel = new SoundChannel();
public var Geer:URLRequest = new URLRequest("Sounds/Gerard Joling heeft er geen kracht meer voor1.mp3");
public var noMoreGeer:Sound = new Sound(Geer);
public var finalScore:TextField;
public function GameOverScherm()
{
opnieuw_button.addEventListener( MouseEvent.CLICK, onClickOpnieuw );
menu_button.addEventListener( MouseEvent.CLICK, onClickMenu );
volumeAdjust.volume = 1;
channelGeer = noMoreGeer.play(0,1);
channelGeer.soundTransform = volumeAdjust;
}
public function onClickOpnieuw( mouseEvent:MouseEvent ):void
{
SoundMixer.stopAll();
GeerGame.instance.switchScreen( "LevelEen" );
gameOverScherm = null;
}
public function onClickMenu( mouseEvent:MouseEvent ):void
{
SoundMixer.stopAll();
GeerGame.instance.switchScreen( "StartScherm" );
gameOverScherm = null;
}
public function setFinalScore( scoreValue:Number ):void
{
finalScore.text = scoreValue.toString();
}
}}
this is the error i get and i cant seem to figure out how to fix it and make the final score appear on the gameoverscreen
C:\Users\Ian-w\Dropbox\game\GeerGame\LevelEen.as, Line 87 1061: Call to a possibly undefined method setFinalScore through a reference with static type Class.
i really hope someone can help me on here, have been stuck on this for a few days
NEWWWW
made the changes and now if i trace(scoreValue) in class GameOverScherm the function setFinalScore i get a response with the correct score, but
public function setFinalScore( scoreValue:Number ):void
{
finalScore.text = scoreValue.toString();
trace(scoreValue)
}
in the GameOverScherm screen the dynamic tekst field name:finalScore does not change value...
aperently i cant post a image so i only post the link http://s29.postimg.org/jwxu6rlfr/Untitled.jpg
what did i do wronge? do i need to update the screen after pusinh the score to the field or something??
There is several errors in your code, tu use this :
GameOverScherm.setFinalScore( finalScore );
you would have to change several things in your class "GameOverScherm" to use the function "setFinalScore" as a static method. I don't think that what you wanted, i see you have :
public var gameOverScherm:GameOverScherm;
Which seems like you wanted to create some sort of "singleton pattern". If so, you need to put this variable as static, then "gameOverScherm" should be set as "gameOverScherm = this" somewhere in your class. This way you would change the line inside "LevelEen" :
GameOverScherm.gameOverScherm.setFinalScore( finalScore );
There is many ways to correct this depending on your code (with or without the use of static methods/variables), but your error say that there is no static function named "setFinalScore". I suggest you to take a look at what's the static word means and how / why to use it.
You are trying to access setFinalScore() from GameOverScherm as though it were a publicly visible static function. Since there is no publicly available function of that name available it returns undefined.
Here is a good write up on how static functions work and when to use them.
It looks like you have a gameOverScherm variable in LevelEen but haven't created a new instance of the GameOverScherm class. You could use this variable to achieve what you're trying to do. You'll need to create a new instance of GameOverScherm in an appropriate place like so:
gameOverScherm = new GameOverScherm();
so you can access its public functions like so:
gameOverScherm.setFinalScore(finalScore);

Receiving a stream of a NetGroup

I'm trying to receive a stream of a NetGroup (television) but it fails at some point. Here is the code (reduced to a testcase):
package lib
{
import flash.events.NetStatusEvent;
import flash.external.ExternalInterface;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.GroupSpecifier;
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.NetStream;
import flash.net.NetStreamPlayOptions;
import mx.core.FlexGlobals;
public class player
{
private var connection:NetConnection;
private var group:NetGroup;
private var group_option:GroupSpecifier;
private var self:Object;
private var stream:NetStream;
private var stream_option:NetStreamPlayOptions;
private var video:Video;
private function _connect():void
{
self.connection = new NetConnection();
self.connection.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
self.connection.connect('rtmfp://p2p.peer-stream.com');
}
private function _event_net_status(event:NetStatusEvent):void
{
if(event.info.code === '')
return;
ExternalInterface.call('echo', 'status', event.info.code, false);
switch(event.info.code)
{
case 'NetConnection.Connect.Success':
self._p2p_start();
break;
case 'NetGroup.Connect.Success':
self._stream_init();
break;
case 'NetStream.Connect.Success':
self._stream_start();
break;
}
}
private function _p2p_start():void
{
self.group_option = new GroupSpecifier('G:0101010c0b0e70726f2073696562656e00');
self.group_option.ipMulticastMemberUpdatesEnabled = true;
self.group_option.multicastEnabled = true;
self.group_option.objectReplicationEnabled = true;
self.group_option.postingEnabled = true;
self.group_option.routingEnabled = true;
self.group_option.serverChannelEnabled = true;
self.group = new NetGroup(self.connection, self.group_option.groupspecWithAuthorizations());
self.group.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_init():void
{
self.stream = new NetStream(self.connection, self.group_option.groupspecWithAuthorizations());
self.stream.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_start():void
{
self.video.attachNetStream(self.stream);
self.stream.soundTransform = new SoundTransform();
self.stream_option = new NetStreamPlayOptions();
self.stream_option.streamName = 'G:0101010c0b0e70726f2073696562656e00';
self.stream.play2(self.stream_option);
}
public function player():void
{
super();
FlexGlobals.topLevelApplication.stage.quality = 'BEST';
self = this;
self.video = new Video(640, 480);
FlexGlobals.topLevelApplication.video_box.addChild(self.video);
self.video.smoothing = true;
self._connect();
}
}
}
The ExternalInterface call there shows me just the passed info in a textfield (I'm testing this in a browser). Here is the result of this output:
NetConnection.Connect.Success
NetGroup.Connect.Success
NetStream.Connect.Success
NetStream.Play.Reset
NetStream.Play.Start
But nothing happens on the player. Here are my thoughts:
I'm using the same string as GroupSpecifier and streamName but I'm assuming this is wrong. If so how can I get the stream name of the NetGroup?
I'm enabling everything from the GroupSpecifier as I don't know what are the minimum requirements to receive a stream and pass it then to another clients. Maybe enabling all makes some troubles here.
Maybe somebody can tell me how I can solve this problem to finally see a stream.
I was able to solve the problem: The streamName was indeed wrong and I could manually figure out the correct name. Also instead of using new GroupSpecifier() I must pass the known group-string directly to the NetGroup and NetStream object.

Simple Camera in Actionscript/flex How to?

I am having no luck with trying to create a simple camera in actionscript. I don't want any controls- just a stage asking for permissions, then a livevideo of me in a window. Nothing fancy
Here's what I have so far: (the latest failure...)
package {
import flash.display.Sprite;
import flash.media.*;
public class FlashCamera extends Sprite
{
var cam:FlashCamera = Camera.getCamera();
var vid:Video = new Video();
vid.attachCamera(cam);
addChild(vid);
}
}
It's throwing this error when I try to compile this:
call to a possibly undefined method getCamera through a reference with static type Class
I'm compiling with flex in the windows command line like this:
(path to SDK)/bin/mxmlc Camera.as
Mind you, I am new to actionscript/flash development.
Can someone please explain what I am doing wrong?
For one thing, you're using classes of the name Camera from two different namespaces without disambiguating between the two. You'll probably also have to import other packages to support API versions of Camera and Video though (flash.media.Camera and flash.media.Video), but I'm not completely convinced this won't be done implicitly, especially not knowing the environment you're using.
Another thing you have to watch out for though, as far as realtime errors go, is when it takes the browser a few seconds to actually get the camera - just keep trying to grab it for at least a few seconds until it returns something other than null.
Found somethng that actually works, and will be adapting it for my needs:
package
{
import flash.display.Sprite;
import flash.events.NetStatusEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Camera;
import flash.media.Microphone;
import flash.media.Video;
public class FlashVideo extends Sprite
{
private var nc:NetConnection;
private var good:Boolean;
private var rtmpNow:String;
private var nsIn:NetStream;
private var nsOut:NetStream;
private var cam:Camera;
private var mic:Microphone;
private var vidLocal:Video;
private var vidStream:Video;
public function FlashVideo()
{
trace("Hello testing");
rtmpNow = "rtmp://localhost/LiveStreams";
nc=new NetConnection();
nc.connect(rtmpNow);
nc.addEventListener(NetStatusEvent.NET_STATUS,checkCon);
setCam();
setMic();
setVideo();
}
private function checkCon(e:NetStatusEvent):void
{
good = e.info.code == "NetConnection.Connect.Success";
if (good)
{
nsOut = new NetStream(nc);
nsOut.attachAudio(mic);
nsOut.attachCamera(cam);
nsOut.publish("left","live");
nsIn = new NetStream(nc);
nsIn.play("right");
vidStream.attachNetStream(nsIn);
}
}
private function setCam()
{
cam = Camera.getCamera();
cam.setKeyFrameInterval(9);
cam.setMode(640,400,30);
cam.setQuality(0,95);
}
private function setMic()
{
mic = Microphone.getMicrophone();
mic.gain = 85;
mic.rate = 11;
mic.setSilenceLevel(15,2000);
}
private function setVideo()
{
vidLocal = new Video(cam.width,cam.height);
addChild(vidLocal);
vidLocal.x = 15;
vidLocal.y = 30;
vidLocal.attachCamera(cam);
vidStream = new Video(cam.width,cam.height);
addChild(vidStream);
vidStream.x=(vidLocal.x+ cam.width +10);
vidStream.y = vidLocal.y;
}
}
}

ActionScript throwing Error #1009 when calling addChild with a TileList as the argument

To be exact this is the error.
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at fl.containers::BaseScrollPane/drawBackground()
at fl.controls::TileList/draw()
at fl.core::UIComponent/callLaterDispatcher()
Now I've tried several of Adobe's own examples from this page, http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/fl/controls/TileList.html, and they all throw this error as well.
The error is triggered by the TileList instance being the argument of the addChild function.
Here's my package, which works fine when I change the displayComponent is be a List.
package com.pennstate {
import fl.data.DataProvider;
import flash.display.MovieClip;
import flash.display.DisplayObjectContainer;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.text.TextFormat;
import flash.xml.XMLDocument;
import com.adobe.serialization.json.JSON;
import fl.controls.List;
import fl.controls.TileList;
public class Sign {
public var displayComponent:TileList;
public var url:String;
public var provider:DataProvider;
public var mc:MovieClip;
public var container:DisplayObjectContainer;
public function Sign( url:String, container ) {
this.container = container;
this.displayComponent = new TileList();
this.mc = new MovieClip();
this.url = url;
this.provider = new DataProvider();
_componentSetup();
loadJson();
_componentFormat();
}
private function _componentSetup() {
displayComponent.labelFunction = getLabelFieldContent;
displayComponent.sourceFunction = getSourceFieldContent;
displayComponent.dataProvider = provider;
displayComponent.selectable = false;
displayComponent.setStyle("contentPadding", 5);
displayComponent.setSize(1720,770);
displayComponent.move(100,200);
displayComponent.rowHeight = 190;
trace('End setup');
}
private function _componentFormat() {
var listTextFormat:TextFormat = new TextFormat();
listTextFormat.font = "Arial";
listTextFormat.color = 0x000000;
listTextFormat.bold = true;
listTextFormat.size = 48;
displayComponent.setRendererStyle("textFormat", listTextFormat);
trace('End formatting');
}
function loadJson():void {
var jsonLoader:URLLoader = new URLLoader();
jsonLoader.addEventListener(Event.COMPLETE, onJsonComplete);
jsonLoader.load( new URLRequest( url ) );
}
function onJsonComplete(e:Event):void {
trace('Loading finished.');
var jsonData:String = e.target.data;
trace(jsonData + "\n");
var decodedData = JSON.decode(jsonData, false);
for (var index in decodedData.rows) {
provider.addItem({title: decodedData.rows[index].node.title, result: decodedData.rows[index].node.Result});
trace(index+" => "+decodedData.rows[index].node.title);
trace(index+" => "+decodedData.rows[index].node.Result);
}
container.addChild(displayComponent);
}
function getLabelFieldContent(item:Object):String {
return new XMLDocument(item.title + "\n" + item.result).firstChild.nodeValue;
}
function getSourceFieldContent(item:Object):String {
return item.result;
}
}
}
You have not given your container agrument in the constructor a type i.e: UIComponent
public function Sign( url:String, container:UIComponent )
This coupled with the fact that its the same name as your member variable is probably the cause.
I had to drag an actual TileList component from the Component Menu onto the Stage using the Flash CS4 GUI to make this error go away.
The weird part is the component that I dragged onto the Stage isn't the component I use in the code. The component I created dynamically in the code now works though.
I even deleted the TileList component that I added to the Stage and it still works. This sounds like a bug to me.

Run-time loading of external assets and re-using preloaded assets in actionscript 3?

I'm creating a 2d flash game (coded in flex/actionscript 3) where assets are downloaded when they are needed. Currently I have it setup like this:
AssetLoader.as
package
{
import flash.display.Loader;
import flash.net.URLRequest;
public class AssetLoader extends Loader
{
//set vars
private var url:String = "http://test.com/client/assets/";
public function AssetLoader(url:String)
{
Logger.log("AssetLoader request: " + this.url + url);
var request:URLRequest = new URLRequest(this.url + url);
this.load(request);
}
}
}
Then, where I want to load the asset I do the following:
var asset:AssetLoader = new AssetLoader("ships/" + graphicId + ".gif");
asset.contentLoaderInfo.addEventListener(Event.COMPLETE, onShipAssetComplete, false, 0, true);
private function onShipAssetComplete(event:Event):void
{
var loader:Loader = Loader(event.target.loader);
shipImage = Bitmap(loader.content);
shipImage.smoothing = true;
addChild(shipImage);
}
The thing is, that this method doesn't check for already downloaded assets, so it will redownload them the second time the same asset is being requested (I think).
So, what I need is an array where all downloaded assets are stored, and on request the name of this asset is checked for existance in the array. So if it has already been downloaded, that asset from memory must be returned rather than redownloaded.
I could make the assetloader a static class, but I have to wait for the event to fire when it's done downloading the image - so I can't simply let a static function return the corresponding image. Any idea how I should do this?
EDIT for an attempt after comments:
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
public final class AssetManager
{
private static var assets:Object = {};
private static var preUrl:String = Settings.ASSETS_PRE_URL;
public static function load(postUrl:String):*
{
if (assets[postUrl])
{ //when the asset already exists
//continue
}
else
{ //the asset still has to be downloaded
var request:URLRequest = new URLRequest(preUrl + postUrl);
var loader:Loader = new Loader();
loader.load(request);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
function(event:Event):void
{
var loader:Loader = Loader(event.target.loader);
assets[postUrl] = loader.content;
}, false, 0, true);
}
}
}
}
EDIT2: another attempt
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLRequest;
public final class AssetManager
{
private static var assets:Object = {};
private static var preUrl:String = Settings.ASSETS_PRE_URL;
public static function load(postUrl:String):*
{
if (assets[postUrl])
{ //the asset already exists
var dispatcher:EventDispatcher = new EventDispatcher();
dispatcher.dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, assets[postUrl]));
}
else
{ //the asset still has to be downloaded
var request:URLRequest = new URLRequest(preUrl + postUrl);
var loader:Loader = new Loader();
loader.load(request);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
function(event:Event):void
{
var loader:Loader = Loader(event.target.loader);
assets[postUrl] = loader.content;
var dispatcher:EventDispatcher = new EventDispatcher();
dispatcher.dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, assets[postUrl]));
}, false, 0, true);
}
}
}
}
Then, I try the following:
var asset:AssetManager = AssetManager.load("ships/" + graphicId + ".gif");
asset.addEventListener(CustomEvent.LOAD_COMPLETE, onShipAssetComplete, false, 0, true);
But get an error, "undefined method addEventListener by a reference of the type static AssetManager" (roughly translated).
You could add a static object (used as a dictionary with urls for assets as keys and the content for assets as values) in the AssetLoader class and in the same time keep using the class in the way you're using it right now.
private static var assets:Object = {};
The difference would be that your class would need to check against that static object if the URL for the content has already been requested previously. If it has, dispatch the complete event immediately. If it hasn't, follow the normal routine and don't forget to populate your static object with the newly loaded asset.
Update:
This is a quick example of what I meant. I haven't had time to test this, but it should work.
Note:
You must invoke the loadAsset() method of the AssetLoader instances you create in order to actually load the asset. This is consistent with the way the Loader class we're extending works.
You should always add all event listeners BEFORE invoking the loadAsset() method. In your question you're calling the load() method from within the constructor and only afterwards add the event listener for Event.COMPLETE. This could produce strange results.
Here's the code:
package
{
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLRequest;
public class AssetLoader extends Loader
{
private static const BASE_URL:String = 'http://test.com/client/assets/';
public static var storedAssets:Object = {};
private var assetURL:String;
private var urlRequest:URLRequest;
private var cached:Boolean = false;
public function AssetLoader(url:String):void
{
trace('Loading: ' + url);
assetURL = url;
if (storedAssets[assetURL] != null)
{
cached = true;
trace('Cached');
}
else
{
trace('Loading uncached asset');
urlRequest = new URLRequest(BASE_URL + assetURL);
contentLoaderInfo.addEventListener(Event.COMPLETE, OnAssetLoadComplete);
}
}
public function loadAsset():void
{
if (cached)
loadBytes(storedAssets[assetURL]);
else
load(urlRequest);
}
private function OnAssetLoadComplete(event:Event):void
{
storedAssets[assetURL] = contentLoaderInfo.bytes;
trace('Loaded ' + contentLoaderInfo.bytesLoaded + ' bytes');
}
}
}
Update 2:
Here's how one would use the class above:
var assetLdr:AssetLoader = new AssetLoader("ships/" + graphicId + ".gif");
assetLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, onShipAssetComplete);
assetLdr.loadAsset();
private function onShipAssetComplete(event:Event):void
{
var shipImage:Bitmap = Bitmap(event.target.loader.content);
// Do stuff with shipImage
}
Perhaps you should take a look at Bulk Loader. It does the kinds of things your looking to do. If you really want to use a custom solution, it would be a great point of reference, but why reinvent the wheel?
Tyler.
Here is an alteration of your load command to capture the resourceId
public function load(postUrl:String):*
{
var index:int;
if ((index = assetExists(postUrl)) != -1)
{
dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, asset[postUrl]));
}
else
{
//the asset still has to be downloaded
var request:URLRequest = new URLRequest(preUrl + postUrl);
var loader:Loader = new Loader();
loader.load(request);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,
function(event:Event)
{
// NOTE: not sure on scoping here ...
// pretty sure you're this will be the Loader
// if not just read it off the event like you were before
assets[postUrl] = content;
dispatchEvent(new CustomEvent(CustomEvent.LOAD_COMPLETE, asset[postUrl]));
}, false, 0, true);
}
}
/* In a new file */
public class CustomEvent extends Event
{
public static const LOAD_COMPLETE:String = "CustomEvent_LoadComplete";
// If you know the type you should use it (e.g. Sprite/DisplayObject)
public var content:*;
public function CustomEvent(type:String, _content:*)
{
content = _content;
super(type);
}
}
Note: when you write an Event descendant you should also override the toString and clone methods. I've also cheated on the constructor since you may want to pass through weakReferences and things like that.