I am trying to load 3 swf files into a parent swf one at a time. However, two of them load the third gives a problem. The other two use my custom preloader but the third one fails to recognize it and shows the default flash loader (with 5 dots). But the loading bar loads up properly. And if I trace this.parent inside my third SWF, it shows up null.
Not sure if I am missing something obvious here but the code for all of them are the same.
package
{
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.MovieClip;
import flash.events.ProgressEvent;
import flash.events.IOErrorEvent;
import flash.events.Event;
import flash.system.Security;
public class PreloaderMain extends MovieClip
{
private var l:Loader = new Loader();
public function PreloaderMain()
{
LoadGame3(); //THIS DOES NOT LOAD UP
}
private function LoaderIOErrorHandler(i:IOErrorEvent):void
{
trace("IOErrorHandler: " + i.toString());
}
private function loop(e:ProgressEvent):void
{
var perc:Number = e.bytesLoaded / e.bytesTotal;
mLoadingScreen.percent.text = (Math.ceil(perc * 100) + "%").toString();
}
private function done(e:Event):void
{
addChild(l);
}
private function LoadGame1():void // THIS LOADS FINE
{
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, LoaderIOErrorHandler);
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("SWF1.swf"));
l.x = 20;
l.y = 100;
}
private function LoadGame2():void //THIS LOADS FINE
{
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, LoaderIOErrorHandler);
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("SWF2.swf"));
l.x = 20;
l.y = 100;
}
private function LoadGame3():void //THIS GIVES A PROBLEM!!
{
l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, LoaderIOErrorHandler);
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("SWF3.swf"));
l.x = 20;
l.y = 100;
}
}
}
Related
We are making an space impact game. Here are 3 of our classes. Our problem is that when we create our InimigoNoite, they appear all over the game(menus, other levels, etc), instead of only appearing in the Scene that we want. How should we restrict the child to only appear in the CenárioCidade?
We've tried to use gotoandPlay, addChildAt, and also tried to create the Inimigo not in the Main class, but in the Inimigo class itself, but it doesnt appear at all. Please can someone help us? Thank you very much!
KEY.as
package {
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class Key {
private static var initialized:Boolean = false;
private static var keysDown:Object = new Object();
public static function initialize(stage:Stage) {
if (!initialized) {
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
stage.addEventListener(Event.DEACTIVATE, clearKeys);
initialized = true;
}
}
public static function isDown(keyCode:uint):Boolean
{
return Boolean(keyCode in keysDown);
}
private static function keyPressed(event:KeyboardEvent):void {
keysDown[event.keyCode] = true;
}
private static function keyReleased(event:KeyboardEvent):void {
if (event.keyCode in keysDown) {
delete keysDown[event.keyCode];
}
}
private static function clearKeys(event:Event):void {
keysDown = new Object();
}
}
}
INIMIGO NOITE.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class InimigoNoite extends MovieClip{
var speed:Number;
static var list:Array = new Array();
var balaTimer: Timer;
function InimigoNoite(){
list.push(this);
this.x = 1160;
this.y = 150 + (450-150) * Math.random();
speed = Math.random()*5 + 5;
addEventListener("enterFrame", enterFrame);
var intervalo: Number = Math.random()*500 + 1000;
balaTimer = new Timer(intervalo);
balaTimer.addEventListener("timer", bala);
balaTimer.start();
}
function enterFrame (e:Event){
this.x -= speed;
if(this.x < -100){
matar();
return;
}
if(this.hitTestObject(SpaceImpact.navecnoite)){
matar();
}
}
function matar(){
var explosao = new ExplosaoNoite();
stage.addChild(explosao);
explosao.x = this.x;
explosao.y = this.y;
balaTimer.stop();
balaTimer.removeEventListener("timer",bala);
removeEventListener("enterFrame", enterFrame);
stage.removeChild(this);
for(var i in list){
if(list[i] == this){
delete list[i];
}
}
}
function bala(e:Event){
var b = new BalaInimigo();
b.x = this.x -50;
b.y = this.y;
stage.addChild(b);
}
}
}
MAIN.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class SpaceImpact extends MovieClip{
static var navecnoite:MovieClip;
var inimigoNoiteTimer:Timer;
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
}
}
You never stop the timer. So your inimigo is created and added every 8seconds.
Stop the timer in criaInimigo and/or use the timerComplete Event
function SpaceImpact(){
Key.initialize(stage);
inimigoNoiteTimer = new Timer(8000,1);
inimigoNoiteTimer.addEventListener(TimerEvent.TIMER_COMPLETE, criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
//inimigoNoiteTimer.stop();//only needed if you use the 'timer'-Event
var inimigo = new InimigoNoite();
stage.addChild(inimigo);
addChildAt(inimigo, 3);
}
Right when you application starts, you are creating a new InimigoNoite every 8 seconds. Since you are adding them to the stage, they will appear over top anything you have on your timeline.
The issue (besides creating them when the application starts and never stopping your timer), is that when you through code use addChild, that child will stay on the screen until it's explicitly removed via removeChild (or one of it's parents are - but since the parent is stage that isn't going to happen).
I see that your have a hit test in the InimigoNoite class that can potentially remove it, but I don't see anywhere else where you remove it (so if the hit test never happens, it will never be removed from the stage regardless of scene).
It seem though that the solution to your problem is more advice on how to architect your application.
Don't use scenes.
Your best bet is to create a class file for each distinct state of your game. So something like this as a basic example:
Main Menu State
Game Play State(either 1 game state that encompasses all levels, or one state for each level - or both - depending on how much functionality changes between levels)
Game Over State
Make your game state class files extend Sprite or MovieClip, and if you want you can even create a new MovieClip in flash pro and attach the class to that (thereby being able to drop visual assets on the timeline).
So then your Main class would just be in charge of managing states (and any anything else that is global to the application)
package{
import flash.display.MovieClip;
import flash.events.Event;
public class SpaceImpact extends MovieClip {
private var menu:Menu; //Assumes you have a Menu.as class file
private var game:MainGame; //MainGame.as file
private var gameOver:GameOver; //GameOver.as file
public function SpaceImpact(){
Key.initialize(stage);
goMenu();
}
public function goMenu(e:Event = null):void {
removeAll();
menu = new Menu();
addChild(menu);
menu.addEventListener(Event.COMPLETE, startGame,false,0,true);
}
private function removeMenu():void {
if(menu){
if(menu.parent) removeChild(menu); //remove it from the screen
menu = null;
}
}
public function startGame(e:Event = null):void {
removeAll();
game = new MainGame();
addChild(game);
game.addEventListener(Event.COMPLETE, gameOver,false,0,true);
}
private function removeGame():void {
if(game){
if(game.parent) removeChild(game); //remove it from the screen
game = null;
}
}
public function gameOver(e:Event = null):void {
removeAll();
gameOver = new GameOver();
addChild(gameOver);
gameOver.addEventListener(Event.COMPLETE, goMenu,false,0,true);
}
private function removeGameOver():void {
if(gameOver){
if(gameOver.parent) removeChild(gameOver); //remove it from the screen
gameOver = null;
}
}
private function removeAll():void {
removeGameOver();
removeMenu();
removeGame();
}
}
}
then, your game state for example:
MainGame.as
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.Timer;
public class MainGame extends MovieClip {
private var inimigoNoiteTimer:Timer;
public function MainGame() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false, 0, true); //don't do anything until this object has been added to the screen
}
private function addedToStage(e:Event):void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
//start spawning
inimigoNoiteTimer = new Timer(8000);
inimigoNoiteTimer.addEventListener("timer", criaInimigo);
inimigoNoiteTimer.start();
}
function criaInimigo(e:Event){
var inimigo = new InimigoNoite();
addChild(inimigo);
}
//when whatever happens that makes your game finished
function gameComplete():void {
dispatchEvent(new Event(addEventListener.COMPLETE));
}
}
}
I have tested the code in action script 2.0 . it is working great but it does not support GIF so i want it write in action script 3.0.
But i have no idea in this.
var current_loader: Number = 1;
import flash.geom.*;
var current_img: Number = 0;
this.createEmptyMovieClip('img_01', 999);
this.createEmptyMovieClip('img_02', 998);
var loader: MovieClipLoader = new MovieClipLoader();
var listener: Object = new Object();
listener.onLoadComplete = function (target_mc: MovieClip) {
if (target_mc._name == 'img_01') {
img_02._visible = false;
} else {
img_01._visible = false;
}
progress_bar.visible = true;
current_loader.opaqueBackground = 0xFF0000;
};
var interval: Number = setInterval(load_image, 1000);
function load_image() {
loader.addListener(listener);
}
loader.loadClip("http://google/Example3", current_loader);
current_loader = current_loader == 1 ? 2 : 1;
current_img = current_img == images.length - 1 ? 0 : current_img + 1;
}
Very simple in as3:
open Flash IDE, create new .fla file, select first frame, open 'actions (f9)' copy code.
Of course in AS3 it's better to use classes to put your code in.
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.HTTPStatusEvent;
import flash.events.IOErrorEvent;
import flash.net.URLRequest;
var imageLoader:Loader = new Loader();
var request:URLRequest = new URLRequest("http://dummyimage.com/600x400/e000e0/fff.gif");
imageLoader.load(request);
addChild (imageLoader);
// and all possible listeners
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
imageLoader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
imageLoader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
imageLoader.contentLoaderInfo.addEventListener(Event.OPEN, openHandler);
imageLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
function completeHandler(event:Event):void {
trace("completeHandler: " + event);
}
function httpStatusHandler(event:HTTPStatusEvent):void {
trace("httpStatusHandler: " + event);
}
function initHandler(event:Event):void {
trace("initHandler: " + event);
}
function ioErrorHandler(event:IOErrorEvent):void {
trace("ioErrorHandler: " + event);
}
function openHandler(event:Event):void {
trace("openHandler: " + event);
}
function progressHandler(event:ProgressEvent):void {
trace("progressHandler: bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
}
see http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html#includeExamplesSummary
There are simpler ways using straight as3 but this a robust way to load may file types with lots of great documentation. https://greensock.com/LoaderMax-AS3
i did like this .And its Working Perfectly.i think it is the simplest .
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.net.URLRequest;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.Event;
public class Example extends Sprite {
public function Example() {
var myTimer:Timer = new Timer(1000);// 1 second
myTimer.addEventListener(TimerEvent.TIMER,runMany);
myTimer.start();
function runMany(e:TimerEvent):void {
var loader:Loader=new Loader();
var url:String= "http://Google.Example3.com/latimage.php";
loader.load(new URLRequest(url));
addChild(loader);
}
}
}
}
I've created 4 instances of Notes and I have them moving to the right until their x value is greater than 100. Once they're there, how do I remove them? I ran a trace statement and confirmed that the parent of these instances is root (root1 to be exact). If I type
root.removeChild(this);
I get an error saying "call to a possibly undefined method removeChild"
If I type
removeChild(this);
I get an error saying "The supplied DisplayObject must be a child of the caller". Full code is posted below. The last line before the }'s at the end is the problem line. Thanks so much for the help!
package
{
import flash.display.Bitmap;
import flash.display.DisplayObject;
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.utils.getDefinitionByName;
import flash.utils.Timer;
import flash.events.TimerEvent;
[Frame(factoryClass="Preloader")]
public class Main extends Sprite
{
private var speed:int = 8;
[Embed(source="../lib/Dodgethis.jpg")]
public var Notes:Class;
public var numnotes:Number;
public var timer:Timer = new Timer(500, 1)
public var rootContainer:DisplayObjectContainer = DisplayObjectContainer (root);
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
timer.start();
timer.addEventListener(TimerEvent.TIMER, testevent);
}
private function testevent(e:Event = null):void {
trace("testevent has run");
appear();
}
private function appear() {
var arr1:Array = new Array;
numnotes = 4;
for (var i = 0; i < numnotes; i++)
{
trace (i);
var nbm:Bitmap = new Notes;
stage.addChild(nbm);
nbm.y = i * 50;
arr1.push(nbm);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
}
private function loop (e:Event):void {
this.x += speed;
trace(this.x) ;
if (this.x > 100) {
removeEventListener(Event.ENTER_FRAME, loop);
trace ("Event listener was removed");
//removeChild(this);
//rootContainer.removeChild (nbm);
/*trace(this.contains)
trace(this.name)
trace(this)*/
trace(this.parent.name); //root
removeChild(this);
}
}
}
}
Try using this in the loop function
e.target.parent.removeChild(e.target);
//or
stage.removeChild(e.target);
You're adding the notes to stage. So you need to remove them from stage.
stage.removeChild( note );
You can only remove a child from its parent, not from any other container. So calling removeChild on a different container will always fail
package com.fladev.background
{
//import all classes
import caurina.transitions.Tweener;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.display.DisplayObject;
import flash.display.StageAlign;
import flash.display.StageDisplayState;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.FullScreenEvent;
import flash.events.MouseEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class MainClass extends Sprite
{
//create variables
private var loaderMenu:Loader;
private var loaderNames:Array = new Array ();
private var loaderContents:Array = new Array ();
private var loaderSlide:Loader;
private var swfDisplayObject:DisplayObject;
private var swfComObject:Object;
private var xmlLoader:URLLoader = new URLLoader();
private var xmlSlideLoader:URLLoader = new URLLoader();
public function MainClass()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, stageResize);
xmlLoader.addEventListener(Event.COMPLETE, showXML);
xmlLoader.load(new URLRequest("navigation.xml"));
//xmlSlideLoader.addEventListener(Event.COMPLETE, showSlideXML);
//xmlSlideLoader.load(new URLRequest("slides.xml"));
}
function showXML(e:Event):void
{
XML.ignoreWhitespace = true;
var menuBtns:XML = new XML(e.target.data);
var i:Number = 0;
for ( i = 0; i < menuBtns.navItem.length(); i++ )
{
loaderMenu = new Loader();
loaderMenu.name = menuBtns.navItem[i].name ;
loaderMenu.load(new URLRequest(menuBtns.navItem[i].swfURL));
loaderMenu.contentLoaderInfo.addEventListener(Event.COMPLETE, createSwfObjects);
}
}
private function createSwfObjects(event:Event):void
{
var swfContent = event.currentTarget.content as MovieClip ;
var swfName = event.currentTarget.loader ;
navigationContainer.addChild(event.target.loader);
showImage(swfContent);
if ( swfName.name == 'topNavigation' )
{
swfContent.addEventListener("clickHandle",topNavigationClickHandler);
}
}
private function topNavigationClickHandler():void
{
trace('Back to root');
}
private function showImage(navigationItem):void
{
try
{
navigationItem.alpha = 0;
Tweener.addTween(navigationItem, { alpha:1, time:1, transition:"easeOutSine" } );
navigationItem.smoothing = true;
} catch (e:Error) { trace('Error no tweening'); };
stageResize();
}
private function stageResize(e:Event=null):void
{
var centerImages:Array = new Array ( contentContainer, navigationContainer, backgroundImage ) ;
backgroundImage.x = 0;
backgroundImage.y = 0;
backgroundImage.scaleX = backgroundImage.scaleY = 1;
if ((stage.stageHeight / stage.stageWidth) < backgroundImage.height / backgroundImage.width) {
backgroundImage.width = stage.stageWidth;
backgroundImage.scaleY = backgroundImage.scaleX;
} else {
backgroundImage.height = stage.stageHeight;
backgroundImage.scaleX = backgroundImage.scaleY;
}
for each ( var centered:MovieClip in centerImages )
{
centered.x = stage.stageWidth / 2 - centered.width / 2;
centered.y = stage.stageHeight / 2 - centered.height / 2;
}
}
}
}
This is my code for the main.as.
And here my code for my loaded SWF on the maintimeline.
addEventListener(Event.ADDED_TO_STAGE, init);
function init(event:Event):void
{
trace('try dispatch');
dispatchEvent(new Event("clickHandle",true));
}
Try dispatch works, but it does not get back to the main to fire up "Back to root".
Any idea?
thx!
As long as all movieclips dispatching events are added to the display list, this should work. This makes me think that perhaps the event listener being added is not working. Try adding a trace statement to the block of code as shown below:
if ( swfName.name == 'topNavigation' )
{
trace("adding listener");
swfContent.addEventListener("clickHandle",topNavigationClickHandler);
}
I expect that this if condition is failing, and thus your listener is never being created. Also, you need to add a function parameter to the callback method "topNavigationClickHandler" to accept the event as the callback parameter. You have not done this, and this is an error that would be thrown at runtime when the event was received and dispatched to the callback method. You havn't seen this yet because your listener has never had to invoke the callback. So you're gonna have to fix this code like so:
private function topNavigationClickHandler(e:Event):void
{
trace('Back to root');
}
Also I just want to add that your if condition on setting this listener seems a bit redundant, since you already know you are expecting the navigation swf, because you're explicitly loading it. Also I don't believe the name property would be set like this. Typically the name is only set inside the IDE before compilation, and if it isn't, it gets dynamically generated at runtime. What might be more useful is to check the URL of the loaded SWF to see if it contains "topNavigation" or whatever the swf name is. You can do this like so:
var swfUrl:String = myLoader.contentLoaderInfo.url;
if (swfUrl.search("topNavigation") != -1){
//Match found, add listener for navigation
}
So at the beginning when my SWF loads up it also loads up a sequence of animated clips like so:
var loader:Loader = new Loader();
loader.load(new URLRequest("clips/clip4.swf"));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, clip4Loaded);
And my clipLoaded function is:
private function clip4Loaded(e:Event):void {
clip4 = e.target.content as MovieClip;
}
The clip4 file being loaded in has a stop() at the first frame. Later in the game (clip4 is the "outro") I use:
clip4.gotoAndPlay(0);
clip4.addFrameScript(clip4.totalFrames - 1, clip4End);
However, the clip only seems to play about 25% of the time and all the other clips which I load the exact same way play fine. The only difference is that those clips get played fairly soon after they load which leads me to believe clip4 is being autoreleased at some point but I really have no clue.
strange - i've got a timeline-animated swf with stop(); in the first frame and the following code:
package {
import flash.display.Loader;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.net.URLRequest;
/**
*
* #author www0z0k
*/
[SWF(width='400', height='300', frameRate='30')]
public class NewClass extends Sprite {
private const URL:String = 'res/1.swf';
private var spr:MovieClip;
public function NewClass():void {
var ldr:Loader = new Loader();
ldr.contentLoaderInfo.addEventListener(Event.INIT, onloaded);
ldr.load(new URLRequest(URL));
}
private function onloaded(e:Event):void {
spr = e.target.content as MovieClip;
addChild(spr);
spr.addFrameScript(spr.totalFrames - 1, function():void { x = x == 0 ? 100 : 0; } );
spr.addEventListener(MouseEvent.CLICK, onclick);
}
private function onclick(e:MouseEvent):void {
spr.gotoAndPlay(0);
}
}
}
and it works exactly as it's written.
could you please upload your clip4.swf anywhere (or test this code with it yourself)?