Flash AS3 game loop : functions on separate frames - actionscript-3

I want to use this to keep my functions on the current frame
function gameloop(e:Event) {
if(currentFrame > 1){
return;
}
}
But I also need to have functions in the game loop separate from frame 1, I just can't do that or else I get the error
duplicate function definition
I need help, and any is appreciated

It sounds like you aren't using OOP, and that is alright. Your problem is that you're remaking functions in subsequent keyframes. If you want to avoid using classes in AS3, the best way is to have a central layer with a single keyframe that spans the entirety of your movie. You put all your global variables and function on there. Then you can access them throughout the entire movie. You are getting a 'duplicate function definition' error because you are rewriting a function rather than extending its scope within the timeline.

Related

Actionscript 3 - How to access integer variable in main timeline from inside MovieClip

First, sorry if my english is bad and I'm new to Actionscript 3.
I have a movieclip, I give it an instance name "symbol1" which include a code inside it, like this :
var a: int = 2;
var b: int = 3;
var total: int = a + b;
How can I access the "total" integer variable inside that movieclip in the main timeline? I try to trace it but the result is 0. In the main timeline I wrote this code :
trace(symbol1.total);
I appreciate the help, thanks
The "problem" is the order of execution of frames. The parent is executed first.
The value is 0 and not undefined because the property does indeed exist since the creation of the object which happens in a previous separate step.
You should be able to verify that by stepping through your code with the debugger.
I've made 6 games. each game is in the MovieClip including the game functions, times, scores, variables, etc. I want the total score of each game summed outside each MoviClips, which is in the main timeline. is there a solution to that problem?
This makes your timing problem even more apparent.
You arrive at a frame, which contains a game and you immediately want to access the total score of it. It should be obvious that the game first has to be played in order to obtain a score from it.
Asking a newborn baby what his favourite moment in the first 60 years of his live was doesn't make much sense.
You have to notify the main timeline that the game was finished. The best way to do this is to dispatch an Event from the game. Frames are totally unnecessary.
Your code could look something like this:
var game:Game = new Tetris();
addChild(game);
game.addEventListener(GameEvent.FINISH, onFinish);
function onFinish(e:GameEvent):void
{
trace("finished game with score " + game.score);
}
If you want to update the exterior score sum while the game is running (to immediately reflect any change in the score, not just when the game is finished), your best bet is to create a ScoreModel for the score which you pass to the game, the Game. The Game modifies the ScoreModel, which in turn causes it to dispatch Events:
var score:ScoreModel = new ScoreModel();
var game:Game = new Tetris(score);
addChild(game);
score.addEventListener(Event.CHANGE, onScoreChange);
function onScoreChange(e:Event):void
{
trace("score changed to " + score);
}
Both examples are "what your code could look like"-type of examples. There are many questions about how to dispatch events that explain how to do this in more detail.
Something that came up in the comments from #Jezzamon:
I'm pretty sure you're accessing the variable total correctly, otherwise I would expect it to cause an error (you can test this by trying to run trace(symbol1.variableNameThatDoesntExist)).
No, there cannot be an error for accessing a variable as seen in the question. The reason for that is that the property is accessed on a MovieClip object, which is a dynamic class. As such, the compiler doesn't know if accessing a particular property is valid, because that can change at runtime. And because nothing else relies on the value to be valid, there isn't a runtime error either.
Here's some example code to illustrate this:
trace("toString: " + {}.toString); //toString: function Function() {}
trace("bananas: " + {}.bananas); //bananas: undefined
This is one of the reasons why using MovieClip can be a bad idea. In addition to that, the Flash IDE modifies the code behind the scenes. That can lead to unexpected execution of code. A purely code based workflow sure is advantageous in this regard and recommended.

Having problems with hitTestObject-ing a child

I've just started to learn actionscript for a month or so, and I've been stuck on this part of the code for about 2 days now ><
So basically, I wanted to write a hitTestObject in a movieclip ("fire_mc") to detect if it overlaps the the child I added on stage (enemy)
So here's what I wrote in the main stage...
var newtarget:enemy=new enemy();
stage.addChild(newtarget);
newtarget.x=40;
newtarget.y=30;
and every time I traced the newtarget in the fire_mc, it turns out to be NULL...
So should I be tracing enemy or newtarget? (Cuz I tried both and nothing works).
And how can I hitTestObject in the fire_mc movieclip?
Is it possible for me to hitTestObject newtarget if I were to create multiple newtarget-s?
If not, what should I do?
And can someone tell me the difference between root, and MovieClip(root) (Because sometimes in a movieclip I have to use the former one to work, and sometimes the latter, and I have no idea why cuz I'm all referencing to the same place)
Sorry for these simple and lengthy questions, I'm really just a noob and I tried looking up for answers in the web for hours, but nothing helpful turned up><
Thanks in advance :)
In this statement
var newtarget:enemy=new enemy();
var - keyword used to define varibles, newtarget - variable name in which pointer to new class instance stored, :enemy - data type (the class name), new - keyword used to create new class instances, and finally enemy is class constructor (by the way there is a rule of good manners by which class names are capitalized)
So answer for you question which should you use when you want check is some is overlapping is 'newtarget'.
Now about hit test - all you need do to check if two objects hit each other is correctly use their references from the part of project where your code is writen.
For example if you have your fire_mc on MainTimeline created by IDE, and code of creation of you enemy instance stored in newtarget sameplace, then if you check will be placed in frame of MainTimeline where both object present it will be like this
fire_mc.hitTestObject(newtarget);
or this
newtarget.hitTestObject(fire_mc);
All these statements give you same result - if objects intersect each other you have true returned.
If you created 'newtarget' on MainTimeline and checks will be from fire_mc (which is on MainTimeline to) frame, then code will something like that
this.hitTestObject(MovieClip(root).newtarget);
Now about root. Primarily it is a property of DisplayObject in which reference to the top-most display object in swf-file structure is stored. So as such it is inherited by all child classes. So here's the trick. When you try get your objects in swf structure using root here the differences are based on the fact that root always return object as DisplayObject and that means what if you object contains something that DisplayObject shouldn't you can't get it. So you must convert returned reference to need data-type usign MovieClip(...).

Access of (as of yet) undefined Property AS3

I have a function that creates a pointer on the screen after certain other conditions are met. I have a separate function that I use for moving the pointer around the screen (since the conditions for the first function and the second function are mutually exclusive). The problem, as far as I can tell, is that upon loading the movie flash instantly looks at all the code on the main timeline and realizes that my second function, the one for moving the pointer, is referencing the pointer's .x and .y even though the pointer doesn't exist. The second function's conditions prevent it from occurring until the first function has executed and the pointer has been created.
My question is, is there any command that I can use to tell flash "pointer.x and pointer.y don't exist YET, but by the time you need them they will, so chill" or do I need to start burying code on the movieclip itself or something? I'm still very new to AS3 so my methods aren't the most... Effective yet.
Yes, there is some. You go into second function and check:
if (!pointer) return;
This will check if "pointer" exists, and is not null or undefined. Basically this is the correct method of programming, first check availability of your objects, then access them.

AS3 - stop onEnterFrame Function from constantly running

Okay, I have a collisionTest function that is tied to my "onEnterFrameHandler" function.
So to simplify the way it looks:
onEnterFrameHandler(e:Event):void{
testCollision();
}
testCollision():void{
trace("always running");
if(1_MC.hitTestObject(2_MC)){
//do stuff
}
}
The thing is, it is always running. Constantly running in order to test for a collision. I have a feeling that it is what may be causing the lag on this project.
Do you know of a good way to control a function that needs to be able to check, at any time, an event, yet not run while the even is not occurring?
Usually you are always checking for collisions in a game loop. You provide a flag to indicate if something needs to be checked or not.
On a side note, consider using collision detection kit, I think you'll find it takes care of just about every scenario you can have regarding collisions.
It's hard to answer this question as it is pretty vague when you're not checking for collision. To improve the performance it's not about changing how to collision test, but when to do the check.
so you could do this by simply adding an if statement like so:
if (doCollisionTest){testCollision();}
but that doesn't solve when doCollisionTest is true or false, and that's the tricky part, that cannot be answered from the information you provided.
If you don't need to check every single frame, you can use a Timer to only check as often as you like, for instance, if you deemed it good enough to check 3 times per second, you'd set it up like this:
var timer:Timer = new Timer(333); //run 3 times a second
timer.addEventListneer(TimerEvent.TIMER, collisionTest, false, 0, true);
timer.start();
function collisionTest(e:Event = null):void {
//do you collision stuffs
}
Then, if for whatever reason you want to temporarily disable it, use timer.stop() , then timer.start() again

Does addEventListener (and removeEventListener) stack?

Given the below:
object.addEventListen(eventType01,handler01);
object.addEventListen(eventType01,handler01);
object.removeEventListener(eventType01,handler01);
How many event listeners for eventType01 are on object? One or zero?
Zero. If you call addEventListener, using the exact same arguments more than once all subsequent calls after the first "silently fail." Call add as many times as you want, but that single remove will wipe the listener away.
EDIT: Another thing to keep in mind is that there's no penalty to calling multiple identical removeEventListener() functions on the same object, aside from needless performance overhead. No deadly error will occur, it will simply "silently fail" much the same way as repeated identical addEventListener calls will.
EDIT 2: To answer #ThomasM :: if your listener "fires twice" then you do not have exactly the same listener. Try putting this quick and dirty code on frame 1 in a fla that has one square movieclip as a child:
import flash.events.*
function foo(e):void{
trace("hi");
}
this.addEventListener(MouseEvent.CLICK,foo);
this.addEventListener(MouseEvent.CLICK,foo);
this.addEventListener(MouseEvent.CLICK,foo);
Notice that your output when you click the movieclip is precisely one trace action.
Now add this line to the end of the code
this.removeEventListener(MouseEvent.CLICK,foo);
Even though you added foo as a listener for click 3 times, this one call kills the listener completely.
So if you're experiencing an issue where "the same listener" fire twice then probably what you're doing is something like this:
this.addEventListener(MouseEvent.CLICK, function(e){
trace("hi");
});
this.addEventListener(MouseEvent.CLICK, function(e){
trace("hi");
});
That will definitely "fire twice" because the listener functions ARE NOT THE SAME. They perform the same actions but they do not reference identical positions in memory. They do not point to the same function object. Furthermore this is highly bad practice because you have no way to actually remove those listeners. How would you do it? You have no reference to them.