AS3 Preloader Cache Problem? - actionscript-3

So the following code is Lee's implementation of a preloader which works fine first load but goes crazy when the browser loads a cached file, jumping from 0% to 100% randomly
Things I have tried to no avail:
switching off gzip compression, tho I dont think it is on
Using ENTER_FRAME instead of progress
and complete
l.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loop);
l.contentLoaderInfo.addEventListener(Event.COMPLETE, done);
l.load(new URLRequest("http://www.foo.com/foo.swf"));
function loop(e:ProgressEvent):void
{
perc = Math.round(e.bytesLoaded / e.bytesTotal * 100);
lt.text = String(perc);
if (perc >= 100)
l.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, loop);
}
function done(e:Event):void
{
l.contentLoaderInfo.removeEventListener(Event.COMPLETE, done);
addChild(l);
}
I do not believe I am loading it more than once:
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);
Security.allowDomain("http://www.foo.com");
preLoader();
}

I discovered the problem happens because the files are hosted on an addon domain.
To fix this I changed the url to reference the main domain:
from
l.load(new URLRequest("http://www.foo.com/foo.swf"))
to
l.load(new URLRequest("http://foo.maindomain.com/foo.swf"))
and also add
Security.allowDomain("http://foo.maindomain.com");

Related

How do i add a countdown timer when the program begins?

I'm creating a game where a spaceship has to collide with planets that are orbiting the centre of the screen. I want there to be a certain time limit so these planets have to be destroyed within the time limit
You can use the Timer class if you want to delay the explosion, if that's what you were getting at:
var myTimer:Timer = new Timer(5000, 1); // delay: 5s
myTimer.addEventListener("timer", timerHandler);
function timerHandler(event:TimerEvent):void {
trace('my planet explodes');
}
function enterFrameHandler(e:Event):void {
if (spaceship.hitTestObject(planet)) {
myTimer.start();
}
}
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
To learn more about Timer class.
You can also create the timer at ADDED_TO_STAGE event, so, your timer will begin when the program stars.
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);
// CREATE YOUR TIMER HERE
}

AS3 mouse events not firing when mouseX = 0

I'm creating what should be a very simple, full screen drag and drop game in Flash Develop. It works fine except in one frustrating instance.
I add items to the stage, add MOUSE_DOWN listeners to them and start dragging when one hears that listener. I then add a MOUSE_UP listener to figure out when to stop the drag. Again, this works fine unless mouseX = 0. When the mouse is all the way to the left of the screen and I mouse up or mouse down no listener is fired. I also took it out of full screen mode and if the mouse is at or below 0 no mouse events will fire.
What in the world is going on?
private function itemSelectedHandler(e:MouseEvent):void
{
thisItem = GameItem(e.currentTarget);
thisItem.startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, itemUnselectedHandler, false, 0, true);
}
private function itemUnselectedHandler(e:MouseEvent):void
{
stopDrag();
stage.removeEventListener(MouseEvent.MOUSE_UP, itemUnselectedHandler);
thisItem.removeEventListener(MouseEvent.MOUSE_DOWN, itemSelectedHandler);
}
You are calling stopDrag on the class and not the dragged sprite. Try something like the following :
package
{
public class Main extends Sprite
{
private var _draggedSprite:Sprite = null;
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
for (var i:int = 0; i < 10; i++)
{
createBox();
}
}
private function createBox():void
{
var sp:Sprite = new Sprite();
sp.graphics.beginFill(0xff0000, 1);
sp.graphics.drawRect(0, 0, 30, 30);
sp.graphics.endFill();
sp.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
sp.x = Math.random() * (stage.stageWidth - 30);
sp.y = Math.random() * (stage.stageHeight - 30);
addChild(sp);
}
private function onMouseDown(e:MouseEvent):void
{
var sp:Sprite = e.target as Sprite;
sp.startDrag();
_draggedSprite = sp;
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onMouseUp(e:MouseEvent):void
{
_draggedSprite.stopDrag();
_draggedSprite = null;
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
}
}
This worked for me when mouseX=0 in fullscreen mode.

(AS3) Functions

I managed to fix the whole null stage error by following MJW's guide on debugging Error #1009. But now the function that initializes the bullets doesn't get called.
Snippets:
if (stage) {
 init();
} else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
...
private function init(event:Event = null) {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(Event.ENTER_FRAME, shoot);
}
...
private function shoot(event:Event) {
var bullet:EnemyBullet = new EnemyBullet();
stage.addChild(bullet);
bullet.x = enemy.x;
bullet.y = enemy.y;
bullet.theta = Math.random() * 360;
bManager.bulletVector.push(bullet);
}
Note that when I put trace() within the second two functions, nothing happens, but the addEventListener() in the first snippet does get called (or so I think).
As a general practice, stage should not be referenced - especially in your case, where your reference is solely to add instances of your bullet class. If it's a matter of z-index, you could instead have a layer in which bullets are placed on top of other display objects on the display list.
Besides complexities loading multiple SWFs on a single stage, your code would become nice isolated functional units by adding display objects to their own hierarchy of the display list. Or, you could leverage a MVC pattern whereby a controller manipulated views.
In order for your code to work, that class must either be the main function of the SWF or added to stage.
If it's the main function of the SWF, init() will be called.
Otherwise, assure it's getting added to the display list via an addChild().
Do you really intend to fire a bullet every frame? That could be 24 to 60 bullets a second. You might want to throttle that with some probability whether a bullet with fire.
Say this was a battlefield, and your battlefield class was added to stage, it could be implemented as this:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
init();
}
protected function init():void
{
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Which would output:
Skip... Odds were: 0.3539872486144304
Skip... Odds were: 0.742108017206192
Fire! Odds were: 0.025597115512937307
Skip... Odds were: 0.7608889108523726
Fire! Odds were: 0.08514392375946045
Skip... Odds were: 0.27881692815572023
Beyond Stage3D, I've never been fond of this initialization pattern, as you could just as easily rely on stage events, as in:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function removedFromStageHandler(event:Event):void
{
removeEventListener(Event.ENTER_FRAME, frameHandler);
removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Therefore, upon added to stage the class initiates its actions, and upon removed from stage the class terminates its actions.
I think the issue is in the first block.
you are checking for stage, if stage is not null, then use a added to stage listener.
you should only be using addEventListener(Event.ADDED_TO_STAGE, init);
however, this is assuming that the class is DisplayObject subclass, objects that do not get added to stage cannot call the ADDED_TO_STAGE listener

Loading an external SWF throw an error

I am trying to load an External swf.
But it throws an error when I compile.
ArgumentError: Error #1063: Argument count mismatch on Main/init(). Expected 0, got 1.
at flash.display::DisplayObjectContainer/addChild()
at flash.display::Stage/addChild()
at MainSWF/onLoadedAction()
Swfloader Class
public function MainSWF():void
{
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_loader = new Loader();
_my_url = new URLRequest("Main.swf");
_loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressAction);
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadedAction);
_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, IOErrorAction);
_loader.load(_my_url);
}
private function onLoadedAction(e:Event):void
{
var mc:Sprite = new Sprite();
mc.addChild(_loader.content);
trace(stage);
stage.addChild(mc);
_loader.removeEventListener(ProgressEvent.PROGRESS, onProgressAction);
}
Init is being called from somewhere else without passing the Event as an argument. Simple solution is to change your init code to look like this:
private function init(e:Event = null):void
{
}
Also you should change your ADDED_TO_STAGE code to look like this:
public function MainSWF():void
{
if(stage){
init();
}else{
addEventListener(Event.ADDED_TO_STAGE, init);
}
}
If you're already added to the stage before you've added the listener, (which is why we check and see if stage is define) then you're never going to fire the ADDED_TO_STAGE event again, unless you add/remove your main swf from the timeline which you most likely won't be doing. So, if you do include that bit of code then it only makes sense to modify the following code as well:
removeEventListener(Event.ADDED_TO_STAGE, init);
to
if(hasEventListener(Event.ADDED_TO_STAGE)){
removeEventListener(Event.ADDED_TO_STAGE, init);
}
Obviously the reason for checking to see if the listener exists is because we may have just jumped right to the init function inside the constructor, because the stage was already present (meaning this swf class was already added to the display list while or before our constructor code executed).

Loading external SWF and last version of FD

(I'm working with FlashDevelop)
I'm having issue loading some external swfs in my project. This worked great until a few month back when they switched the preloader integration with :
[Frame(factoryClass="Preloader")]
Since then my swf loaded with a Loader() doesn't show.
Any idea of what changed ?
Thanks !
Code :
public class Main extends Sprite
{
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
loadMovie("Dots.swf");
}
private function loadMovie(url:String):void {
var mLoader:Loader = new Loader();
mLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.load(new URLRequest(url));
}
private function onCompleteHandler(loadEvent:Event):void {
trace("COMPLETE");
addChild(loadEvent.currentTarget.content);
}
private function onProgressHandler(event:ProgressEvent):void {
trace("progressHandler: bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
}
private function ioErrorHandler (e:IOErrorEvent):void {
trace("ERROR");
}
}
Is "COMPLETE" getting traced out? I can't tell too much from the code you posted here, there could be something else going on, particularly in Dots.swf.
The one thing I see right off the bat is that your loader object may be getting garbage collected, but if it is tracing out "COMPLETE" that definitely is not the case. Try adding loader to the display list right away and see if that makes a difference. eg:
var mLoader:Loader = new Loader();
addChild(mLoader);
I do all my work in Flash Develop and have not had any issues with this. If you are able to share more code, or example project, I could investigate further.