I have a question. I'm beginner so...
I'm creating website on flash and i have 5 pages and 5 buttons(menu buttons) and I need to use menu so I wrote this code but aobe flash writes error 1120, whats a problem?;s
thisi is code
{stop();
function projectsButton_clicked (e:MouseEvent) :void {
gotoAndStop("projects");
}
function galleryButton_clicked (e:MouseEvent) :void {
gotoAndStop("gallery");
}
function videosButton_clicked (e:MouseEvent) :void {
gotoAndStop("videos");
}
function backstageButton_clicked (e:MouseEvent) :void {
gotoAndStop("backstage");
}
function pricelistButton_clicked (e:MouseEvent) :void {
gotoAndStop("pricelist");
}
function contactButton_clicked (e:MouseEvent) :void {
gotoAndStop("contact");
}
projectsButton.addEventListener(MouseEvent.CLICK, projectsButton_clicked);
galleryButton.addEventListener(MouseEvent.CLICK, galleryButton_clicked);
videosButton.addEventListener(MouseEvent.CLICK, videosButton_clicked);
backstageButton.addEventListener(MouseEvent.CLICK, backstageButton_clicked);
pricelistButton.addEventListener(MouseEvent.CLICK, pricelistButton_clicked);
contactButton.addEventListener(MouseEvent.CLICK, contactButton_clicked);
}
Well, there are a couple of things wrong in your code:
The useless braces at the beginning and end of the program { }, but I don't think that affects much.
If you're using scenes, this is how gotoAndStop should be used: gotoAndStop(frame, "Scene name"); , unless they're all frames of a movieclip, in that case you should just use the frame number. Here you go: http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001310.html
Those were just notes since those might cause errors later, the most likely cause of your error is that one or a couple of buttons mentioned in the code (projectsButton, galleryButton, videosButton, etc...) don't actually exist, they either aren't on the stage or when you were naming them on the stage you misspelled one/some of them. I think you should double check all their instance names.
That's all I can think of, best of luck with your website! ^^
Related
I'm trying to create something similar to Impossible Quiz Question 5 (1st quiz). However the hitTestPoint appears to be not reading. I'm not exactly sure where my error is.
Here is my full line of code.
stop();
blueTarget.addEventListener(MouseEvent.MOUSE_OVER, mousehandler2);
function mousehandler2(e:MouseEvent):void {
if (blueTarget.hitTestPoint(mouseX,mouseY,true)) {
removeEventListener(MouseEvent.MOUSE_OVER, mousehandler2);
gotoAndStop("lose");
}
}
nexttButton.addEventListener(MouseEvent.MOUSE_DOWN, mousehandler3);
function mousehandler3(e:MouseEvent):void {
removeEventListener(MouseEvent.MOUSE_DOWN, mousehandler3);
MovieClip(root).nextFrame();
}
Thanks for the help!
Do you want the player to lose if he passes the mouse over the blueTarget? If so, you can remove your if statement because the mouse over event is already added to the blueTarget
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!
Okay, so I came up with this brilliant idea earlier to practice ActionScript 3.0, I decided I would create a flappy bird clone. I have the basic bird movements down, so the bird can move up and down appropriately and he'll rotate and it looks really slick.
But I have a problem with a boolean variable and an if statement. It isn't really bothering the code being there but I would like to know why it is doing what it is doing. If you run this code below in flash with your own symbol called bird, it'll work fine. You can press any button and the bird will fly up and the fall back down.
var hasGameStarted:Boolean=false
//input stuff
stage.addEventListener(TouchEvent.TOUCH_TAP, tap1);
stage.addEventListener(KeyboardEvent.KEY_DOWN, tap1);
function tap1(event):void{
if (!hasGameStarted){
startGame();
}
}
function startGame():void{
hasGameStarted=true;
var jumpLevel:int=10
var jumpLevelCap:int=36
removeEventListener(KeyboardEvent.KEY_DOWN, tap1);
removeEventListener(TouchEvent.TOUCH_TAP, tap1);
stage.addEventListener(Event.ENTER_FRAME, update);
stage.addEventListener(TouchEvent.TOUCH_TAP, tap2);
stage.addEventListener(KeyboardEvent.KEY_DOWN, tap2);
function update(event):void{
bird.y+=jumpLevel;
//gravity
if (jumpLevel<jumpLevelCap){
jumpLevel+=6;
}
//rotation
if (bird.rotation<100 && bird.rotation>-90 && jumpLevel>0){
bird.rotation+=jumpLevel;
}
if (bird.rotation<100 && bird.rotation>-100 && jumpLevel<0){
bird.rotation+=jumpLevel*2;
}
if (bird.rotation>=100){
bird.rotation=99;
}
if (bird.rotation<-90){
bird.rotation=-89;
}
//out of bounds
if (bird.y<1){
killBird();
}
}
function tap2(event):void{
jumpLevel=-30;
}
function killBird():void{
}
}
However, if you run the exact same code with all things pertaining to the boolean variable hasGameStarted removed from the code or commented, the program will get ridiculously fast. There are no other variables depending on this boolean, and it is not needed at all.
//var hasGameStarted:Boolean=false
//input stuff
stage.addEventListener(TouchEvent.TOUCH_TAP, tap1);
stage.addEventListener(KeyboardEvent.KEY_DOWN, tap1);
function tap1(event):void{
//if (!hasGameStarted){
startGame();
//}
}
function startGame():void{
//hasGameStarted=true;
...
If you need to know exactly what happens, it will pretty much function the same besides the bird will move ridiculously fast and will move faster every time you press a button.
Please help, I'm still learning, I started like a week ago.
You added the listener tap1 for TouchEvent.TOUCH_TAP to Stage, but in startGame you are removing it from the current object, not Stage (at lines 17 & 18). If you don't have that boolean, every tap call will call startGame.
The solution is to correctly remove the previous listeners:
stage.removeEventListener(KeyboardEvent.KEY_DOWN, tap1);
stage.removeEventListener(TouchEvent.TOUCH_TAP, tap1);
I have been dealing with this problem for days already. I am at my wits' end!
I can't seem to find a definitive answer anywhere on any of the forums, documentation, etc.
Everything looks fine at first run, or when I load a next level for the user to play. But if the user hits the ESC key to load a different level, the ENTER FRAME listener does not get removed and it duplicates all the triggers in it, showing the player going really fast, and all funky, because it builds on top of the previously instantiated ENTER FRAME listener.
I don't know if I have a problem of an anonymous function, or an unknown instance being referenced in my removeEvent... command... Bottom line, I give up and I need this working HELP!!!
Here's the code:
function initPlay():void
{
//code here determining what display object to add to the list and assign it to the currentLevel variable (a movieclip)
if(userIsLoadingOtherLevel){
removeEnterFrameListener();
addChild(currentLevel);
}
if(userIsGointToNextLevel)
addChild(currentLevel);
currentLevel.addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(event:Event):void
{
//collision detection, parallax scrolling, etc, etc is done here.
if(allCoinsCollected)
loadNextLevel();
if(ESCKeyPressed)
ESCKeyPressHandler();
}
function loadNextLevel():void
{
removeChild(currentLevel);
newLevelToLoad++
removeEnterFrameListener();
initPlay();
}
function ESCKeyPressHandler():void
{
removeChild(currentLevel);
initPlay();
}
function removeEnterFrameListener();
{
currentLevel.removeEventListener(Event.ENTER_FRAME,onEnterFrame)
trace("currentLevel.hasEventListener(Event.ENTER_FRAME) = "+currentLevel.hasEventListener(Event.ENTER_FRAME)); //outputs TRUE if called from loadNextLevel but FALSE if called from initPlay() !!!
}
}
I also tried to add and remove the eventListener to stage, MovieClip(Root), or nothing at all and the result is always the same.
I know that there may be other ways to design such a process, but please note I am not really flexible at the moment on doing this because the project is very long (about 4000 lines of code) and removing the ENTER FRAME this way, crazy or not should still work!!
THANK YOU in advance for anyone willing to help.
The problem appears to be the nested functions inside the initPlay() method.
Each time you call initPlay() you are defining new functions. Some of these nested functions call initPlay() themselves.
Functions are objects (memory references). So each time you call initPlay() you are making new references to new functions. So when you try to remove an event listener, you're only able to remove one of these event handlers (the one in the current scope of execution).
I'm not sure if I'm explaining this clearly, perhaps this example will help. I'll use numbers to represent the references to each function, and a simple scenario that is similar to yours:
function example():void
{
addEventListener(MouseEvent.CLICK, mouseClickHandler);
function mouseClickHandler(event:Event):void
{
if (someCondition)
{
example();
}
else
{
removeEventListener(MouseEvent.CLICK, mouseClickHandler);
}
}
}
When we run this function the first time, a new function is defined within the scope of the example() function. Lets use the number 1 to represent the reference to this nested function. someCondition is true on the first time around, and so the example() function is called again.
On the second execution of the example() function, a new reference to the mouse event handler is created (#2). We also add the event listener again. At this point, there are two event handling functions in memory, and both will be executed when the event is dispatched.
Let's say that in the second invocation of example() that someCondition is false and now we want to remove the listener. When we call:
removeEventListener(MouseEvent.CLICK, mouseClickHandler);
It's referring to event handler #2. Event handler #1 still exists, and because it's hidden in the scope of the first invocation of example() it can't be removed here.
My simple example breaks down after this... but I hope it makes it clear why your event handlers shouldn't be nested inside a function. Admittedly, this is difficult to describe and even more so in a real world example like yours. But I'm pretty confident that this is the source of most, if not all, of the issues you describe.
Here's how I was able to get around this without changing the scope of the nested functions (although I agree that would be the preferred solution) by creating a boolean variable called "loadingNewGame" and changing it to true from outside the onEnterFrame (in fact, this assignment was done from initPlay() and then from onEnterframe I called removeEnterFrameListener() function. This did the trick.
here's the code in case anybody is interested:
// package, and other code here.
var loadingNewGame:Boolean = new Boolean(false);
function initPlay():void
{
//code here determining what display object to add to the list and assign
//it to the currentLevel variable (a movieclip)
if(userIsLoadingOtherLevel)
{
loadingNewGame = true;
removeEnterFrameListener();
addChild(currentLevel);
}
if(userIsGointToNextLevel)
addChild(currentLevel);
loadingNewGame:Boolean = false;
currentLevel.addEventListener(Event.ENTER_FRAME, onEnterFrame);
function onEnterFrame(event:Event):void
{
if(loadingNewGame)
removeChild(currentLevel);
//collision detection, parallax scrolling, etc, etc is done here.
if(allCoinsCollected)
loadNextLevel();
if(ESCKeyPressed)
ESCKeyPressHandler();
}
function loadNextLevel():void
{
removeChild(currentLevel);
newLevelToLoad++
removeEnterFrameListener();
initPlay();
}
function ESCKeyPressHandler():void
{
initPlay();
}
function removeEnterFrameListener();
{
currentLevel.removeEventListener(Event.ENTER_FRAME,onEnterFrame)
trace("currentLevel.hasEventListener(Event.ENTER_FRAME) = "+currentLevel.hasEventListener(Event.ENTER_FRAME));
//outputs true
}
This is my code in Flash/AS3, in main class.
addEventListener(Event.ENTER_FRAME,function(e:Event){
if(findObject == true){
// I want to remove this ENTER FRAME
}
});
try this:
e.currentTarget.removeEventListener(e.type, arguments.callee)
You shouldn't be doing what you do in the code above.
The mgraph's code has a tiny chance of failing to work as advertised if the currentTarget of the event doesn't have a removeEventListener() method (possible, but very unlikely). From the compiler standpoint though you will be trying to dynamically resolve the method on a generic object which is error prone and should be handled with care. This is hazardous because it shows that the programmer "did not know" what kind of object was she expecting to handle and worked by assumption. Assumptions are great for finding a solution but are equally bad for implementing one.
If you thought of optimizing something in the way you did it, then, just FYI this actually creates a unique (redundant) name in the symbol table (in the compiled SWF file) which causes worse compression of the SWF.
If you are doing this as a matter of experiment, this is fine, but you should avoid such code in real life projects.
One more thing to be aware of: comparison to true constant is 100% useless. If such comparison makes any sense at all (i.e. findObject may evaluate to false any time), then if (findObject) { ... } is equivalent but shorter version of your code.
Last thing, hopefully, the anonymous function is missing return type declaration. It won't really change much in your example, except that you will get compiler warning. Omitting type declaration is, in general, a bad style.
EDIT
public function addEventListener(type:String, listener:Function ...):void
{
this._listeners[type].push(listener);
}
public function dispatchEvent(event:Event):void
{
for each (var listener:Function in this._listeners[event.type])
listener(event);
}
public function removeEventListener(type:String, listener:Function, ...):void
{
delete this._listeners[type][listener];
}
Suppose you actually want to implement IEventDispatcher (instead of using another EventDispatcher - you may have your reasons to do so, one such reason is that native EventDispatcher generates insane amounts of short-lived objects - events, and you may want to reduce that.) But there is no way you can replicate event.target or event.currentTurget in your code because you can't access the object owning the method, so, you would leave that out.
Another example:
public class SomeEvent extends Event
{
private var _target:NotEventDispatcher;
public function SomeEvent(type:String, someTarget:NotEventDispatcher)
{
super(type);
this._target = someTarget;
}
public override function get target():Object
{
return this._target;
}
}
This is something that I actually saw in real world, this was used in either Mate or similar framework to sort of "anonymously" connect all event dispatchers to a single static instance of some "mothership event dispatcher".
I don't necessarily justify this approach, but, technically, nothing stops you from doing either one of these. What I was saying in my post above is that in certain situations the language promises you things, like, if you did:
var dispatcher:IEventDispatcher;
try
{
dispatcher = IEventDispatcher(event.currentTarget);
// now you can be sure this object has removeEventListener
dispatcher.removeEventListener(event.type, arguments.callee);
}
catch (error:Error)
{
// but what are you going to do here?
}
But the most common case would be you subscribing to a bubbling event, in which case, you don't know whether you want to unsubscribe from event.target or event.currentTtarget - because you don't know which one is that you are listening to.
I agree with wvxvw.
Another way to approach your problem is to have a variable to control the "state" of your ENTER_FRAME event:
private var _state:String;
private function init(e:Event):void {
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event):void {
switch(_state) {
case "play":
// do play stuff
// when you want to pause
// goToPause();
break;
}
}
// you can call the method below from a button or whatever you want
private function goToPause():void {
_state = "pause";
// do some stuff here
// when you are done, switch "_state" back to "play"
}
In this example, you keep listening for ENTER_FRAME, but it only does things when the _state variable is set to "play". You can also remove the event listener in the goToPause method:
private function goToPause():void {
_state = "pause";
removeEventListener(Event.ENTER_FRAME, loop);
}
However, the nice thing about using the "_state" to switch things is that you don't end up having a mess of addEventListeners and removeEventListeners (which is what can happen depending on how complicated your loop gets) that you have to keep track of.
You should not use anonymous function call if you would like to remove listener some time later.
public function main():void
{
//...
//some method, where you add event listener
//...
//adding enterFrame event listener
this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
//...
}
private function enterFrameHandler(e:Event)
{
if(findObject) // " == true" is not really necessary here.
{
// removing enterFrame listener:
this.removeEventlistener(Event.ENTER_FRAME,enterFrameHandler);
}
}
Just for a completeness with the other techniques mentioned here, the function you are creating is a unbound closure, so you can also leverage that concept to reference both your function and dispatcher.
var callback:Function;
var dispacher:IEventDispatcher = this;
addEventListener(Event.ENTER_FRAME, callback = function(e:Event){
if(findObject == true){
dispacher.removeEventListener(Event.ENTER_FRAME, callback);
}
});
Normal closed-over variable rules apply.