i've never had to do any cross scripting until now and i'm running into a (probably really stupid) error right at the start.
External SWF: i've created a new ActionScript 3.0 project in Flash Professional CS5. on the first frame i've added the following script:
//Square.fla frame script
import flash.display.Shape;
import flash.events.Event;
var s:Shape = new Shape();
s.graphics.beginFill(0x0000FF, 1.0);
s.graphics.drawRect(-100, -100, 200, 200);
s.graphics.endFill();
s.x = stage.stageWidth / 2;
s.y = stage.stageHeight / 2;
addChild(s);
addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
function enterFrameEventHandler(evt:Event):void
{
s.rotation += 2;
}
save, compile, done. this works fine as a stand alone swf, which simply displays a rotating blue square at center stage.
Main SWF: i've create开发者_StackOverflow中文版d a new ActionScript 3.0 file in Flash Professional CS5, which has a document class called CrossScriptTest:
//CrossScriptTest.as
package
{
//Imports
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Sprite
import flash.display.Loader;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.events.Event;
//Class
[SWF(width = "1000", height = "500", backgroundColor = "0x444444")]
public class CrossScriptTest extends Sprite
{
//Constants
private static const SQUARE_SWF_URL:String = "Square.swf";
//Variables
private var SWFLoader:Loader;
//Constructor
public function CrossScriptTest()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
init();
}
//Initialize
private function init():void
{
SWFLoader = new Loader();
SWFLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
SWFLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteEventHandler);
SWFLoader.load(new URLRequest(SQUARE_SWF_URL));
}
//IOError Event Handler
private function IOErrorEventHandler(evt:IOErrorEvent):void
{
trace(evt);
}
//Loader Complete Event Handler
private function loaderCompleteEventHandler(evt:Event):void
{
evt.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
evt.currentTarget.removeEventListener(Event.COMPLETE, loaderCompleteEventHandler);
var squareSWF:Sprite = Sprite(evt.currentTarget.content);
addChild(squareSWF);
}
}
}
Error: i receive the following error:
TypeError: Error #1009: Cannot access a property or method of a null object reference. at Square_fla::MainTimeline/frame1()
perhaps i'm misunderstanding the nature of cross scripting or loading external swf files, but i can only seem to make this work if i've manually drawn display objects on the stage and not if the external swf's display objects are generated by code.
is it not possible to load external swfs that are programatically created and add them to the display list of a main swf?
the solution is always so obvious after the fact. the solution is, of course, to assign an Event.ADDED_TO_STAGE
event listener in the constructor or initialize method of the external swf's document class.
in my defense this was overlooked since it is not required nor common when creating a standard (internal?) document class.
Main SWF's Document Class:
package
{
//Imports
import flash.display.StageScaleMode;
import flash.display.StageAlign;
import flash.display.Sprite
import flash.display.Loader;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
import flash.events.Event;
//Class
[SWF(width = "1000", height = "500", backgroundColor = "0x444444")]
public class CrossScriptTest extends Sprite
{
//Constants
private static const SQUARE_SWF_URL:String = "Square.swf";
//Variables
private var swfLoader:Loader;
//Constructor
public function CrossScriptTest()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
stage.frameRate = 60;
init();
}
//Initialize
private function init():void
{
swfLoader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteEventHandler);
swfLoader.load(new URLRequest(SQUARE_SWF_URL));
}
//IOError Event Handler
private function IOErrorEventHandler(evt:IOErrorEvent):void
{
trace(evt);
}
//Loader Complete Event Handler
private function loaderCompleteEventHandler(evt:Event):void
{
evt.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR, IOErrorEventHandler);
evt.currentTarget.removeEventListener(Event.COMPLETE, loaderCompleteEventHandler);
addChild(evt.currentTarget.content);
}
}
}
External SWF's Document Class:
package
{
//Imports
import flash.display.Sprite;
import flash.display.Shape;
import flash.events.Event;
//Class
public class Square extends Sprite
{
//Constructor
public function Square()
{
init();
}
//Initialize
private function init():void
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);
}
//Added To Stage Event Handler
private function addedToStageEventHandler(evt:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageEventHandler);
var s:Shape = new Shape();
s.graphics.beginFill(0x0000FF, 1.0);
s.graphics.drawRect(-100, -100, 200, 200);
s.graphics.endFill();
s.x = stage.stageWidth / 2;
s.y = stage.stageHeight / 2;
addChild(s);
s.addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
//Enter Frame Event Handler
function enterFrameEventHandler(evt:Event):void
{
Shape(evt.currentTarget).rotation += 2;
}
}
}
Yes it can be done, but the way you are doing it doesn't seem right. You could simply use a loader:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener("complete", loader_complete);
loader.load(new URLRequest("yourfile.swf"));
function loader_complete(event:*):void {
var loadedObject:* = event.target;
// Access the properties of the loaded SWF here
}
Edit:
In general, try not to use frame scripts, especially when loading SWFs within SWFs, because the way they work is not always obvious. For instance, I don't know what the root is in your script - is it the root of your SWF or that of the parent SWF? (I don't know because, to avoid this kind of problem, I never use frame scripts). To avoid that, you can simply use a document class and put all your code in there.
Maybe try something like that and see if it works:
package some.unique.path {
import flash.display.MovieClip;
import flash.display.Shape;
import flash.events.Event;
public class YourClass extends MovieClip {
public function YourClass():void {
var s:Shape = new Shape();
s.graphics.beginFill(0x0000FF, 1.0);
s.graphics.drawRect(-100, -100, 200, 200);
s.graphics.endFill();
s.x = stage.stageWidth / 2;
s.y = stage.stageHeight / 2;
addChild(s);
addEventListener(Event.ENTER_FRAME, enterFrameEventHandler);
}
function enterFrameEventHandler(evt:Event):void
{
s.rotation += 2;
}
}
}
精彩评论