AS3 Loader doesn't unload after game reset - actionscript-3

you have always been of great help for me throughout the last few years.
I could always find a solution to my programming problem.
This time however I couldn't find a solution to this one.
Although there are a few topics which discuss Loaders. Mine is a lot different.
The problem:
In the first game screen I load a movie (a movie converted to .swf).
And after I switch to the next state, it unloads and doesn't display any more.
At the end of the game I execute my own made reset function (which has not much to do
with the loader whatsoever, it just resets some static variables) and the game switches
to the first state.
The Loader once again shows up. But now when I switch states, the Loader is still displaying.
Note: I am using the flixel library. Although I don't think it makes a big difference in this case (though I figure it problably does since I still have the problem :P).
I have only placed the important code. I have three buttons. Let's say I push. the third button. In the switch case I enter case 2.
The reset function is a flixel function: FlxG.resetGame() but I figure it doesn't really
matter.
I hope this is enough information for someone to see the problem/solution.
Thanks in advance.
Here's the code:
AMCInlog.as
private var my_loader:Loader;
private var my_player:Object;
public function AMCInlog()
{
imgBackground = new FlxSprite(0, 0, Resources.imgStartMenuBackground);
add(imgBackground);
my_loader = new Loader();
my_loader.x = 40;
my_loader.y = 156;
my_loader.scaleX = 1.2;
my_loader.scaleY = 1.2;
//loadUserData();
moviePlayerSequence();
//userData.clear();
//createButtons();
}
private function moviePlayerSequence():void {
var request:URLRequest = new URLRequest("DGAME Movie.swf");
my_loader.load(request);
FlxG.stage.addChild(my_loader);
}
private function currentButtonFunction():void {
switch(currentButton) {
case 0:
my_loader.unloadAndStop();
FlxG.stage.removeChild(my_loader);
FlxG.switchState(new AMCRegister());
break;
case 1:
my_loader.unloadAndStop();
FlxG.stage.removeChild(my_loader);
FlxG.switchState(new AMCExistingAccountLogin());
break;
case 2:
my_loader.unloadAndStop();
FlxG.stage.removeChild(my_loader);
FlxG.switchState(new AMCPreferences());
break;
default:
break;
}
}

You never reset your loader, hence it just holds onto what it loaded last time, either simply try and reset (or re-initiate actually) your loader like so (not the best method (will go into flash garbage-collection which has never been that awesome) but hey, it works)
my_loader = new Loader();
Or (since i dont see it) try using simply unload(); instead of unloadAndStop(); (since well, you dont need to stop it, if you unload it properly, its gone anyway)
Good luck!

Related

Checking a Boolean variable in another class

Let me set the stage because it's too much code to post everything:
I have a Main.as that is setting up my SoundController.as so I can trigger sounds from any other class (SoundController.as has all the functions needed to call all my sounds as needed)
I have a ControlPanel.as that can access these sounds by using docRef.soundControl.laserFire or whatever other function name I want, and in this case the laserFire sound would trigger once.
So here is my question. I want to let this laser sound effect finish playing before you can fire another laser. So in SoundController.as I've set up the following pieces of code:
private var _laserPlaying:Boolean = false;
internal function laserFire():void {
_sfxChannel = _laser.play(25);
_laserPlaying=true;
_sfxChannel.addEventListener(Event.SOUND_COMPLETE, laserFinished);
}
internal function laserFinished(event:Event):void {
_sfxChannel.removeEventListener(Event.SOUND_COMPLETE, laserFinished);
_laserPlaying=false;
}
public function get laserPlaying():Boolean {
return _laserPlaying;
}
public function set laserPlaying(value:Boolean):void {
_laserPlaying = value;
}
Now in my ControlPanel class in the enterFrameHandler function I want to do an
if (docRef.soundControl.laserPlaying()==false)
or something to that effect so I can check when the sound is done and allow the player to once again press the trigger to fire the laser. So far any variant I've tried on this either gives me an error (in this case 1195; Attempted access of inaccessible method laserPlaying through a reference with static type SoundController) or it actually compiles but after firing the first laser shot it never allows the trigger to be pressed again. So I'm obviously doing something wrong and am hoping someone can help.
Let me just state that the laser sound is playing just fine that first time, so don't worry about all the code I'm not bothering to show to make that portion of the code work. However, if more info is needed to understand how I'm making anything work just let me know. And Thanks in advance!
If your soundController AND ControlPanel are instantiated in Main:
handle the firing event, in ControlPanel, like this:
if(MovieClip(parent).soundController.soundChannel.position==0)
{
MovieClip(parent).soundController.laserfire();
}else{do nothing;}
Of course use proper instance names.
If this doesn't work you'll have to make your code a little easier to understand.
Sorry for wasting everyone's time. I ended up figuring out what I needed to do to make this work. This probably won't be of much use to anyone else since my setup was probably unique to my layout and not something that anyone else will try, but here is what I did anyway.
In my ControlPanel.as I added the following code:
private var _soundController:SoundController;
And then I have a function that waits for the ControlPanel to be added to the stage and once that occurs I fired:
_soundController = new SoundController(docRef);
Now by adding those I was able to simply call:
if(!_soundController.laserPlaying) { do stuff; }
It now seems to wait for laserPlaying to be false and then moves on as intended.

Check the existence of an object instance

I'm surprised I don't know how to do this, but as it turns out I really don't; simply put, I'm trying to make a side-scrolling shooter game, a basic one and in it, I have 50 stars spawned on-screen through a "for" loop upon the game starting. There is a function which does this and a listener is at the beginning. Problem is, when you lose the game and go back to main menu, 50 more stars would be spawned, which isn't what I want. So, I'm trying to make an "if" statement check at the beginning, so that the game checks whether there is an instance/movie clip of the star object/symbol before determining whether the function that spawns stars should be called out with a listener. So, how do I do this? I looked through some other checks and they didn't help as the codes presented were vastly different there and so I'm just getting errors.
Let me know if a better explanation is needed or if you would like to see some of the code. Note that the game overall already has a lot of code, so just giving all of it would probably not be helpful.
I suggest you rethink your approach. You're focusing on whether stars have been instantiated. That's ok but not the most basic way to think about it.
I would do this instead
private function setup():void{
loadLevel(1);
addListeners();
loadMusic();
// etc...
// call all functions that are needed to just get the app up and running
}
private function loadLevel(lev:int):void{
addStars();
// call all functions that are needed each time a new level is loaded
}
private function restartLevel():void{
// logic for restarting level,
// but this *won't* include adding star
// because they are already added
}
There are other ways to do this but this makes more sense to me than your approach. I always break my game functions into smaller bits of logic so they can be reused more easily. Your main workhorse functions should (IMHO) primarily (if not exclusively) just call other functions. Then those functions do the work. By doing it this way, you can make a function like resetLevel by assembling all the smaller functions that apply, while excluding the part about adding stars.
Here's what I did to solve my problem... Here's what I had before:
function startGame():void
{
starsSpawn();
//other code here
}
This is what I changed it to:
starsSpawn();
function startGame():void
{
//other code here
}
when you said existance, so there is a container, i named this container, (which contain stars , and stars was added to it) as starsRoot, which absolutely is a DisplayObject (right?)
now, to checking whole childrens of a DisplayObject, we have to do this :
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
}
then, how to check if that child is really star!?
as you said
whether there is an instance/movie clip of the star
so your stars's type is MovieClip, and they don't have any identifier (name), so how to find them and make them clear from other existing movieclips. my suggestion :
define a Linkage name for stars from library, thats a Class name and should be started with a capital letter, for example Stars
now, back to the code, this time we can check if child is an instance of Stars
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
if (child is Stars) {
// test passed, star exist
break;
}
}

Stop MouseEvent-propagation of displayList views to starling views

I'm creating a game that uses the starling-layer (the game itself) and the classic display list which contains several Popups and Stuff like that.
I have one thing that troubles me:
If MouseEvents are generated on displayList-elements they always go through to the starling layer and produce TouchEvents etc. which is quite annoying.
I was wondering there is some general (and easy to use) approach to handle that.
One possibility was to listen on all displayList-Elements for the following Events:
interfaceElement.addEventListener(MouseEvent.MOUSE_MOVE, stopPropagationHandler);
interfaceElement.addEventListener(MouseEvent.MOUSE_DOWN, stopPropagationHandler);
interfaceElement.addEventListener(MouseEvent.MOUSE_UP, stopPropagationHandler);
private function stopPropagationHandler(e:MouseEvent):void {
e.stopPropagation();
}
But this looks quite nasty to me.
And even if I did it like that, I have one more issue:
If a starling-element is below that display-list-element and if it has a TouchEvent.TOUCH for rollover-behavior >> the rollover-appearance will not be removed from the starling if you hover over the display-list-element.
I also thought about putting a dummy-starling element behind every display-list-element,... to stop the events.. but that all sounds a bit "over-complicated" for such a "simple" task.
Or am I missing something?
A hint would be much appreciated.
Thanks.
You could create 1 main container in the displaylist (not the stage) and listen for ROLL_OVER and ROLL_OUT, and set somekind of global flag there, that your mouse is over the display-list container. Then in your starling events, check for this flag. This isn't the nicest solution out there i guess, but it should work
var isOverDisplayList:Boolean = false;
container.addEventListener(MouseEvent.ROLL_OVER, onRollOver);
container.addEventListener(MouseEvent.ROLL_OUT, onRollOut);
function onRollOver(e:MouseEvent) {
isOverDisplayList = true;
}
function onRollOut(e:MouseEvent) {
isOverDisplayList = false;
}

Flash AS3 typewriter with some extra effects

I'm trying to recreate the effect seen on this page: http://flupie.net/blog/2010/12/typewriter-effect-with-textanim-as3/ (example #2)
But without all the separate files.
The reason why I dont just use that code, is because A) It uses text that's in a string, and I want to be able to apply the effect to textfields. B) It uses separate .as files, and I want it all to be 1 file (I want to upload this on DeviantArt later, and as far as I know, you can only upload the .swf)
So is it possible to recreate that matrix style typewriter effect, without resorting to separate .as files and apply it to textfields? I'm really more of a designer than a programmer, so this is just a little too much for me.
EDIT: To get some more clarification on what I intend to achieve. I want to build a character sheet for a fictional character (think: name, appearance, background, etc) and since this character is in the future, I want to give it a futuresque feeling. So the end result will contain several separate textfields and possibly some images. All these textfields should "run" at the same time. Perhaps I'll also add some more "pages" but I'm assuming this is done by just adding another frame to the timeline and a button to link to it.
I'm currently trying to decipher the code linked above, since that is precisely what I'm aiming to achieve, font and glow effects included.
I've written a class (just for you! - but it's quite simple and I'm bored...) which you can use to achieve this effect. Obviously, it's in your interest to take a look at this code at some point, but I'll show you how to use it - and it's very simple - without knowing how it works:
In flash, create a new ActionScript file, copy the code below into it and save it as TypeFX.as - in the SAME directory as your .fla project file:
package {
import flash.utils.Timer;
import flash.text.TextField;
import flash.events.TimerEvent;
public class TypeFX {
private var timer:Timer;
private var text:String;
private var pos:int = 0;
private var field:TextField;
public function TypeFX(field:TextField, speed:int = 200, text:String = null) {
// constructor code
this.field = field;
if(text != null)
{
this.text = text;
}
else
{
this.text = field.text;
}
field.text = '';
timer = new Timer(speed, this.text.length);
timer.addEventListener(TimerEvent.TIMER,update);
timer.addEventListener(TimerEvent.TIMER_COMPLETE,kill);
timer.start();
}
private function update(e:TimerEvent):void
{
pos++;
field.text = text.substr(0,pos);
}
private function kill(e:TimerEvent):void
{
timer.removeEventListener(TimerEvent.TIMER,update);
timer.removeEventListener(TimerEvent.TIMER_COMPLETE,kill);
timer.stop();
timer = null;
text = null;
field = null;
}
}
}
Again, you don't need to understand that to use it, but it's quite simple when broken down, you might enjoy looking at how it works.
Now, take a TextField you want to apply a typewriter effect to - make sure it's set as 'Dynamic Text' and give it an instance name. For example's sake, let's call it myField - now, open the Actions panel. You can apply this effect in a couple of ways:
If you want to create a typewriter effect with the text which is already in the field (it'll clear it, then type it out), add the following code to the actions panel:
new TypeFX(myField);
This will type out the text which was present in the field with a 200ms interval between letters - if you want to change this interval, add a second argument:
new TypeFX(myField,500);
This increases the delay to 500ms
You can also send a string to type out, as opposed to using the text already in the field (this is recommended, it'll be easier to read later, trust me!):
new TypeFX(myField, 500, "The text to type into the field");
Just note that if you are using this method (passing a string) you need to specify a time (eg 500 above), you can't leave it blank like you can if you're just using the field text.
Hope this helps, let me know if you get stuck!

The framerate of one movieclip slowly declines over time. What could cause this? [Flash CS3]

I'm creating a flash rhythm game. I have a looping (at a certain frame I have a gotoAndPlay) movieclip that contains the notes that scroll by, which loops for about three minutes. As the level progresses, the movieclip's framerate begins to lag and stutter. As far as the movieclip is concerned, no variables or functions are being called that would cause this. I have no idea how this could occur. It is also worth mentioning that the notes are represented by text (non-rasterized text), if that makes any difference. As far as posting my code goes, I think it would be far too convoluted to be worth your time. I just don't understand how the framerate of this movieclip could drop independent of the rest of the game.
EDIT: Following Sam's advice, I found the chunk of code that is slowing down my game.
if(_noteBar._decide)
{
if(_noteBar._correctHits == _noteBar._correctNumberHits)
{
_noteBar._totalCorrect = true;
}
else if(_noteBar._correctHits > 0) {}
else
{
_noteBar._decrement = true;
}
}
This chunk of code runs every frame. I honestly don't understand how this could bring down the framerate so much. I'm just checking and assigning some variables. Also, this is pretty much crucial to the functioning of my game. Could it be that I'm checking variables from a different class?
Try removing your code as much as possible (commenting it out) and then slowly add it back in until you find the spot that is causing the slowdown.
That code certainly doesn't look like it could cause a slowdown. How many times is it being run per frame? Should you be setting _noteBar._decide = false before you exit the if? Can you add an extra check to make sure it only runs once per frame? In Flex this is done through invalidateProperties/commitProperties but I don't know the equivalent in Flash.
The code can be optimized a little, but I doubt it will make a difference.
var noteBar = _noteBar;
if(noteBar._decide)
{
va correctHits = noteBar._correctHits;
if(correctHits == _noteBar._correctNumberHits)
{
_noteBar._totalCorrect = true;
}
else if(correctHits > 0)
{
}
else
{
noteBar._decrement = true;
}
}