ENTER FRAME stops working without error - actionscript-3

When does ENTER_FRAME stops?
1. removeEventListener(Event.ENTER_FRAME,abc);
2. error occurs or the flash crashes
3. the instance of class is removed from stage
4. ?
The story:
I have several AS document for a game,one of it contains ENTER_FRAME which adding enemies.
It works fine usually,but sometimes it don't summon enemies anymore. I didn't change anything,I have just pressed Ctrl+enter to test again.
I have used trace to check, and found the ENTER_FRAME stops.
Otherwise, I put trace into another AS file of ENTER_FRAME, it keeps running.
Another ENTER_FRAME in levelmanage class for testing if it's working, both of it and addEventListener(Event.ENTER_FRAME, process); stops too
I also don't get any errors, and I can still move my object via keys.
The levelmange class doesn't connect to any object,it shouldn't stop if anything on stage has removed.
what could be the problem?
The below as code is the one who stops operating.
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.utils.*;
public class levelmanage extends MovieClip
{
var testing:int=0
private var sttage = ninelifes.main;
public var framerate = ninelifes.main.stage.frameRate;
public var levelprocess:Number = 0;
public var levelprocesss:Number = 0;
private var level:int;
public var randomn:Number;
public function levelmanage(levell:int)
{
level = levell;
addEventListener(Event.ENTER_FRAME, process);
}
function process(e:Event)
{
testing+=1
if(testing>200){
testing=0
trace("working")//it don't trace "working"sometimes which means enterframe doesn't going
}
if (levelprocess>levelprocesss)trace(levelprocess);
levelprocesss = levelprocess;
if (levelprocess>=100 && enemy.enemylist.length==0)
{
finish();
return();
}
if (levelprocess<=100 && enemy.enemylist.length<6)
{
switch (level)
{
case 1 :
arrange("cir",0.5);
arrange("oblong",1);
break;
}
}
}
public function arrange(enemyname:String,frequency:Number)
{
randomn = Math.random();
if (randomn<1/frequency/framerate)
{
var theclass:Class = Class(getDefinitionByName(enemyname));
var abcd:*=new theclass();
sttage.addChild(abcd);
trace("enemyadded")
switch (enemyname)
{
case "cir" :
levelprocess += 5;
break;
case "oblong" :
levelprocess += 8;
break;
}
}
}
private function finish()
{
levelprocess=0
trace("finish!");
removeEventListener(Event.ENTER_FRAME,process);//not this one's fault,"finish" does not appear.
sttage.restart();
}
}
}

It's possible you eventually hit "levelprocess==100" and "enemy.enemylist.length==0" condition, which causes your level to both finish and have a chance to spawn more enemies, which is apparently an abnormal condition. It's possible that this is the cause of your error, although unlucky. A quick fix of that will be inserting a "return;" right after calling finish(). It's also possible that your "levelmanage" object gets removed from stage somehow, and stops receiving enter frame events, which might get triggered by a single object throwing two "sttage.restart()" calls. Check if this condition is true at any time in your "process" function, and check correlation with this behavior. And by all means eliminate possible occurrence of such a condition.

if(testing>200){
testing=0
trace("working")//it don't trace "working"sometimes which means enterframe doesn't going
}
The deduction in your comment isn't correct. It means either EnterFrame isn't firing, or testing <= 200.
Try putting a trace right at the beginning of your process function.
If you don't have removeEventListener elsewhere, then it is unlikely EnterFrame is really stopping - it's hard to be sure from the example you've posted but I would bet the problem is somewhere in your logic, not an issue with the EnterFrame event itself.

Related

AS3 MOVING OBJECT ON SPECIFIC FRAME

so i've been working on this game for a week now and i dont have any coding background at all so im trying to find tutorial here and there.. then i come up with this problem ...
so what i wanna do is move the object (CHARA) to the right when i hit frame 80 inside (CHARA,which is a nested movieClip with 99 frames btw ) then move it back to original position when i hit frame 99...
the problem is anything i do doesn't make my object move at all (movieClip still played btw) what did i do wrong here? did i just put the code at the wrong position ?? (CHAR is moved only if i put the code x= directly inside frame 80 but i try using class here)
here is my code,sorry i know its messy its my first code i try my best here
package {
public class Main extends MovieClip {
public var CHARA:CHAR = new CHAR;//my main char
public var rasen:Rasen_button = new Rasen_button;//the skill button
public var NPCS:NPC = new NPC;// the npc
public function Main() {
var ally:Array = [265,296];//where me and my ally should be
var jutsu:Array = [330,180];// where the buttons should be
var enemy:Array = [450,294];//where the enemies should be
addChild(NPCS);
NPCS.x = enemy[0];
NPCS.y = enemy[1];
NPCS.scaleX *= -1;
addChild(rasen);
rasen.x = jutsu[1];
rasen.y = jutsu[0];
addChild(CHARA);
CHARA.x = ally[0];
CHARA.y = ally[1];
rasen.addEventListener(MouseEvent.CLICK, f2_MouseOverHandler);
function f2_MouseOverHandler(event:MouseEvent):void {
CHARA.gotoAndPlay(46); //here is the problem
if (CHARA.frame == 80)
{
CHARA.x = ally[1]; //just random possition for now
}
}
}
}
}
any suggestions?
Your if statement is inside a click handler (f2_MouseOverHandler), so it only gets executed when a user clicks rasen, not necessarily when the playback reaches frame 80. This is a common beginner mistake related to timing and code execution. The most straight forward solution is to write some code that will execute every frame using an ENTER_FRAME handler:
rasen.addEventListener(MouseEvent.CLICK, f2_MouseOverHandler);
function f2_MouseOverHandler(event:MouseEvent):void {
CHARA.gotoAndPlay(46); //here is the problem
// add an ENTER_FRAME handler to check every frame
CHARA.addEventListener(Event.ENTER_FRAME, chara_EnterFrameHandler)
}
function chara_EnterFrameHandler(event:Event):void {
if (CHARA.currentFrame == 80)
{
CHARA.x = ally[1]; //just random possition for now
// remove the ENTER_FRAME after the condition is met
// so it stops executing each frame
CHARA.removeEventListener(Event.ENTER_FRAME, chara_EnterFrameHandler);
}
}

SImple Coloring Book: Error #1009: Cannot access a property or method of a null object reference

I am creating a simple flash coloring book and am not very familiar with as3 programming language.
I entered the following code,and when I attempted to press the back button in the test movie I got that error.
stop();
back_btn.addEventListener(MouseEvent.CLICK, GoToChooseA);
function GoToChooseA(event:MouseEvent):void
{
gotoAndStop("Choose");
}
color_scroll.mask = myMask;
var goY: Number = color_scroll.y;
stage.addEventListener(Event.ENTER_FRAME, scrollManage);
function scrollManage(Event): void {
color_scroll.y += (goY - color_scroll.y) / 20;
}
up_btn.addEventListener(MouseEvent.MOUSE_DOWN, scrollUP);
down_btn.addEventListener(MouseEvent.MOUSE_DOWN, scrollDown);
function scrollUP(MouseEvent): void {
goY += 20;
}
function scrollDown(MouseEvent): void {
goY -= 20;
}
*
It seems to indicate the error is here
color_scroll.y += (goY - color_scroll.y) / 20;
But I'm really bummed because I'm not really sure how to proceed from there.
Whenever you gotoAndStop() to a different keyframe, your current frame is invalidated and all its members destroyed. Listeners persist, if they are attached to an object that persists. So, right after you call GoToChooseA(), your color_scroll is destroyed, and then the listener attached to stage is called and tries to modify a destroyed object, there goes your 1009. The solution is either manually remove the event listeners "scrollManage", "scrollUp", "scrollDown" before you change the frame, at least "scrollManage" because it's attached to stage, or stop using frames altogether, but even then you'll have to control your event listeners.
You could add some logic to your function to check if you are in the right frame and then proceed. I am not familiar with frames so the condition would be something like this._currentframe == 2 or timeline.currentFrame == 2.
function scrollManage(Event): void {
if ( condition ) {
color_scroll.y += (goY - color_scroll.y) / 20;
}
}
If you are not at the right frame (in my example that is frame 2), the function does not execute any code.
This error means you are trying to modify something that is no longer existent.

Custom Event Listener not working

I am new to as3 and I recently saw creation of custom events in as3 in a tutorial and I wanted to incorporate in my game. When i did the tutorial, it all seemed well for that project. But it doesnt seem to work with the new project.
Here is my code :
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class FashionFrenzy extends MovieClip
{
public var Buyer_mc:Buyer;
public var Buyers:Array;
public var gameTimer:Timer;
public function FashionFrenzy()
{
GameTimeController();
GenerateBuyers();
addEventListener(ReachMallDoorEvent.CHECK, OnReachMallDoor);
}
public function GameTimeController()
{
gameTimer = new Timer( 25 );
gameTimer.start();
}
public function GenerateBuyers()
{
Buyers = new Array ;
Buyer_mc = new Buyer(533.2,0) ;
addChild(Buyer_mc);
gameTimer.addEventListener( TimerEvent.TIMER, BuyerEnter );
if(Buyer_mc.y==377.25)
{
dispatchEvent( new ReachMallDoorEvent( ReachMallDoorEvent.CHECK ) );
}
}
public function BuyerEnter(event:TimerEvent)
{
Buyer_mc.Enter();
}
public function OnReachMallDoor(event:ReachMallDoorEvent)
{
trace("my timer starts now");
}
}
}
Here, OnReachMallDoor never seems to run because there is something wrong. I cant see the output saying "My timer starts now". But there is no error in the code and output doesnt show any runtime errors either. Where have I gone wrong? I want OnReachMallDoor function to run when my y coordinate is in desirable position and the event is dispatched.
The order of commands is wrong.
GenerateBuyers();
addEventListener(Rea...
The first line of these two is the one that could potentially cause the Event to be dispatched. But only after that will you start listening for it. That's simply too late. You have to start listening before the Event is dispatched.
The probability of the Event to be dispatched is very low.
Buyer_mc.y==377.25
Checking floating point values for equality is often not a good idea. It could easily be just slightly off due to rounding errors etc. If this .y property was controlled by the mouse for example, you'd have to position the mouse at exactly that position, which is very unlikely.
You only dispatch the Event at the beginning.
GenerateBuyers();
That function is only called once. The .y position is evaluated.
This only happens once and never again.
But the .y position is subject to change and the condition should be evaluated again, which doesn'T happen
The structure is not helpful.
It doesn't make much sense for an object to listen for its own Events. Simply call the function and be done with it.
Events are for communication between objects.
How this is supposed to be:
The point of the custom Event is to be notified about something.
You want to be notified when this condition
Buyer_mc.y==377.25
is true.
If you are evaluating that condition the way you do it now, then there's no point in receiving a notification about the result thereof. You have it already.
Instead, Buyer_mc should dispatch the Event. The condition should be checked in Buyer class.
What the code looks like
some snippets pointing out what the above means, code untested:
class Buyer
override public function set y(value:Number):void
{
if (value == 377.25)
dispatchEvent(new ReachMallDoorEvent(ReachMallDoorEvent.CHECK)); // I'm at the position, I send out the notification
super.y = value;
}
class FashionFrenzy
buyer = new Buyer(533.2, 0); // variables should start with small letter
buyer.addEventListener(ReachMallDoorEvent.CHECK, OnReachMallDoor);
If you now set the .y position to the value, the object will dispatch the Event. It will figure that out on its own.
Letting the object figure something out on its own and just receive a notification about it is the main reason to use custom events.

External ActionScript Only Executed When Testing Single Scene

New to AS 3.0 and I seem to have an issue where an external AS file is run when I test an individual scene in Flash Pro but not when I test the entire movie or when I test from Flash Builder. Anyone know what the problem might be?
Here's the code from the AS file:
package {
import flash.display.MovieClip;
public class Level1 extends MovieClip {
public var myplayer:MyPlayer;
public function Level1() {
super();
myplayer.x = 516;
myplayer.y = 371;
if (myplayer.x == 516)
{
trace("player x is 516");
}
else if (myplayer.y == 371)
{
trace("player y is 371");
}
}
}
}
Any ideas?
EDIT
I think I figured out the problem. The swf contained two scenes, and the external AS file started running at the start of Scene 1, but the myPlayer movie clip was not instantiated until Scene2, which, I think was causing the problem I was having, in addition to giving a 1009 null object error.
So I simply deleted the first scene, and now everything works fine. Maybe I will put that first scene in a separate SWF? Or, is there some way to delay a script's execution until a certain scene?
Your problem:
When the constructor of your doucment class runs, myPlayer doesn't yet exist so it throws a 1009 runtime error and exits the constructor at the first reference to myPlayer.
Solutions:
Put all the myPlayer code on the first frame of the MyPlayer timeline. OR use your current document class as the class file for MyPlayer (instead of documentClass). Change all references to myPlayer to this.
Listen for frame changes and check until myPlayer is populated, then run your code.
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
function enterFrameHandler(e):void {
if(myPlayer){
//run the myPlayer code
this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
}
}
If your frame rate is 24fps, this code though will run 24 times every second (until it finds myPlayer), so it's not the most performant way to go.
Use events. Add an event to the first frame of myPlayer (or to a class file for MyPLayer) that tells the document class that it exists now.
stage.dispatchEvent(new Event("myPlayerReady"));
Then listen for that event on the document class:
stage.addEventListener("myPlayerReady",playerReadyHandler);
playerReadyHandler(e:Event):void {
//your player code
var myPlayer = MyPlayer(e.target); //you can even get the reference from the event object
}
Thanks for your constructive, helpful responses, LDMS. I thought I had found a solution when I hadn't. Your advice worked. What I did was add the following code to the timeline of MyPlayer
this.x = 516;
this.y = 371;
if (this.x == 516)
{
trace("player x is 516");
}
if (this.y == 371)
{
trace("player y is 371");
}
and I removed the code from the document class. Everything seems to be working fine now. Thanks again for your help!

New instances not resetting its Timers and Childs

(I'm working in AS3 and Adobe AIR for iOS SDK).
The program has two classes: the first one is Program.as which is what the FLA file is linked to. In Program.as there's a function to start the program and another to restart the program. The second class is my Main.as class which calls the finishNow(); function from Program.as to restart the program.
It runs fine on its first run-through. The problem is that nearly as soon as it restarts, it seems to KEEP restarting itself on its own. It gives quite a few ArgumentError: Error #2025: The supplied DisplayObject must be a child of the caller. errors too. I've also noticed that some functions such as TIMERS do not start from 0 again when the program restarts?? I'm really stumped because the logic seems to be okay, but the traces say otherwise.
Putting traces inside Program.as shows that the finishNow(); function is being called repeatedly after the first run. The problem lies with the programRestartTimer not resetting on the new instance. By calling the stop(); function on programRestartTimer temporarily fixes this. From the Error #2025 that keeps showing, I suspect that display Childs which were not removed (or similar – such as other Timers also not resetting) in the first run are causing this problem. This would suggest that either the program is NOT creating an entirely new instance, or it is not possible with AS3??
Program.as:
package {
import flash.display.MovieClip;
public class Program extends MovieClip {
var runMain:Main;
public function Program() {
startNow();
}
function startNow() {
runMain = new Main(this);
addChild(runMain);
}
function finishNow() {
removeChild(runMain);
runMain = new Main(this);
addChild(runMain);
}
}
}
Main.as:
package {
import flash.display.Sprite;
public class Main extends Sprite
{
public var program:Program;
var programRestartTimer:Timer = new Timer(8 * 1000);
public function Main(stageHolderTemp) {
program = stageHolderTemp;
trace(program);
someFunctionsThatDrawGraphics();
moreFunctions();
}
function callFinishFunction():void { // this is called at the end of the animation
programRestartTimer.start();
programRestartTimer.addEventListener(TimerEvent.TIMER, restartProgram);
}
function restartProgram(e:TimerEvent):void {
programRestartTimer.stop(); // this line is a temporary "fix" to stop the program from constantly restarting
// it doesn't actually fix the full problem
program.finishNow();
}
}
}
It sure is possible in AS3 to design a class so that it will be able to re-initialize itself. But this requires carefully devising the restart routine.
First, your callProgramRestart() function adds a listener to the Program instance, but it is never removed, this will cause your program to reset twice after the second call, which is most likely the cause of your remove child errors - you are removing them twice in a row. You can completely eliminate the need of that listener by utilizing flash.utils.setTimeout() (the manual) and targetting it to call restartProgram function.
function callFinishFunction():void { // this is called at the end of the animation
flash.utils.setTimeout(restartProgram,8000);
}
function restartProgram():void {...}
Second, you should do the "full" reinitialization somewhere. Your method of creating another instance of Main class should most likely work, but you should clear your listeners off former Main instance properly before calling this.