Flash CS6 Error #1009 - Button disappears - actionscript-3

I'm starting to use Flash CS6 for the first time to try and make Scaleform UI's for UDK. I'm following this simple tutorial: http://goo.gl/yedMU. I've followed it to the letter but can't seem to get it to work. I even have tried it again in a new project but it ends up with the same error. I've triple checked each name and instance but it just refuses to work. Here is the really simple code of the two frames in the file:
import flash.events.MouseEvent;
import flash.system.fscommand;
import flash.display.MovieClip;
subMenu_btn.addEventListener(MouseEvent.CLICK, subMenu);
exit_btn.addEventListener(MouseEvent.CLICK, exitGame);
var cursor:cursor_mc = new cursor_mc();
addChild(cursor);
cursor.x = mouseX;
cursor.y = mouseY;
cursor.startDrag();
stop();
function subMenu(event:MouseEvent):void
{
gotoAndStop('Sub Menu');
}
function exitGame(event:MouseEvent):void
{
fscommand('ExitGame');
}
and
play_btn.addEventListener(MouseEvent.CLICK, playGame);
back_btn.addEventListener(MouseEvent.CLICK, backBtn);
function playGame(event:MouseEvent):void
{
fscommand('PlayMap');
}
function backBtn(event:MouseEvent):void
{
gotoAndStop('Main Menu');
}
I used the debugger and the code breaks at
exit_btn.addEventListener(MouseEvent.CLICK, exitGame);
Any ideas? The whole thing works until I used the 'Back' button to go back to the first frame, when the 'Exit' button is gone and I get that error. The 'Submenu' button remains however and the menu is still operable.
This is the error using the debugger:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Menu_fla::MainTimeline/frame1()[Menu_fla.MainTimeline::frame1:6]
at flash.display::MovieClip/gotoAndStop()
at Menu_fla::MainTimeline/backBtn()[Menu_fla.MainTimeline::frame2:10]

Okay, so I might have been wrong in what I said in the comments above, the solution is this:
For your first frame's AS3:
import flash.events.MouseEvent;
import flash.system.fscommand;
import flash.display.MovieClip;
var cursor:cursor_mc = new cursor_mc();
subMenu_btn.addEventListener(MouseEvent.CLICK, subMenu);
exit_btn.addEventListener(MouseEvent.CLICK, exitGame);
addChild(cursor);
cursor.x = mouseX;
cursor.y = mouseY;
cursor.startDrag();
Mouse.hide();
stop();
function subMenu(event:MouseEvent):void
{
subMenu_btn.removeEventListener(MouseEvent.CLICK, subMenu);
exit_btn.removeEventListener(MouseEvent.CLICK, exitGame);
removeChild(cursor);
gotoAndStop('Sub Menu');
}
function exitGame(event:MouseEvent):void
{
fscommand('ExitGame');
}
For your second frame's AS3:
play_btn.addEventListener(MouseEvent.CLICK, playGame);
back_btn.addEventListener(MouseEvent.CLICK, backBtn);
cursor = new cursor_mc();
addChild(cursor);
cursor.x = mouseX;
cursor.y = mouseY;
cursor.startDrag();
Mouse.hide();
function playGame(event:MouseEvent):void
{
fscommand('PlayMap');
}
function backBtn(event:MouseEvent):void
{
removeChild(cursor);
gotoAndStop('Main Menu');
}
You were instantiating the cursor each time you hit frame 1, which I believe would create a namespace problem. The solution was to remove the cursor from the stage, and add it back in for each frame. There may be a more elegant solution, but as I never use multiple frames with AS (for this very reason), this is the best I could do. I also hid the mouse cursor to give your cursor_mc more focus.
Let me know if you have any other questions.
Happy coding!

Another solution would be to create a new layer, and put the cursor code on that layer only. That layer would have one keyframe, and extend to cover the entire timeline, so it is always alive.
Or, create a menu movie clip that exists on frame 1. And inside that movie clip, have your different frames for each part of the menu (options, etc.). And the cursor would exist at the same level as the menu movie clip. So it always exists and is only initialized once.

Related

FLASH AS3 Sound Overlap

Alright, I'm a total noob in flash as3 so this must be very easy to solve I guess. I'm making a soundboard with recorded voices in flash cs6, very simple: 1 frame, ten buttons, each button makes a different sound. The problem is the overlapping of these sounds, so what I need is that when I press one button the other sounds stop playing. anyone please?
See the play() method documentation in the Sound class, it returns a SoundChannel object, which has a stop() method.
So you could do it like that (schematically) :
var currentChannel:SoundChannel;
button1.addEventListener(MouseEvent.CLICK, onButtonClick);
button2.addEventListener(MouseEvent.CLICK, onButtonClick);
button3.addEventListener(MouseEvent.CLICK, onButtonClick);
function onButtonClick(event:MouseEvent):void
{
/* provided you have implemented selectSoundByButton func somewhere */
const sound:Sound = selectSoundByButton(event.currentTarget);
if (currentChannel) {
currentChannel.stop();
}
currentChannel = sound.play();
}
More detailed description:
Let's say you want to create yet another fart button application in flash. That's what you have to do:
Create a button symbol, add it to stage and give it an instance name in properties tab. Let's call it myButton
Add the sound to library with file->import
Export this sound to actionscript. Right click on a sound in library, check "Export for actionscript", "export in frame 1" on "actionscript tab". Fill "Class" input with a desired class name for a sound (e.g. MySound)
Then you have to trigger the sound playback on your button click. So you should put the following code to the first frame of your flash clip:
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.MouseEvent;
var currentChannel:SoundChannel;
const mySound:Sound = new MySound();
function onClick(e:MouseEvent):void {
if (currentChannel) {
currentChannel.stop();
}
currentChannel = mySound.play();
}
myButton.addEventListener(MouseEvent.CLICK, onClick);
Add this to your code on each button before playing a sound:
SoundMixer.stopAll();
If you're adding actions directly from the timeline in Adobe Flash, there's no need to import the class. If you're working from an IDE like FlashDevelop or FlashBuilder, add this code to the beginning (after Package {):
import flash.media.SoundMixer;
Happy coding!
Edit: More info on the SoundMixer class

ColorTransform for multiple movie clips

Despite searching both the web and youtube for a solution, it remains difficult to find information on colorTransforming multiple movie clips in AS3. I found a video on youtube about colorTransform which i followed steps to create a fully functional colorTransform for a single clip but i would like to use it for multiple clips and be able to change colors for each on a mouse click.
I have included the code below and perhaps someone knows how i can add more movie clips to it. When i copy and change mc1. EventListener code to mc2, i get a duplicate function error which i don't know how to fix.
import flash.geom.ColorTransform;
import flash.geom.ColorTransform;
import flash.events.MouseEvent;
// this here is the little movieclip where the main clip gets its color from,the clip is made up of two movieclips but can also be one movieclip
// instead of brushColor i have used myColor and instead of brush.tip i have used square.
var myColor:ColorTransform=new ColorTransform();
myColor.color=0xffffff; square.transform.colorTransform=myColor
red.addEventListener(MouseEvent.CLICK,onclick);
green.addEventListener(MouseEvent.CLICK,onclick);
blue.addEventListener(MouseEvent.CLICK,onclick);
orange.addEventListener(MouseEvent.CLICK,onclick);
yellow.addEventListener(MouseEvent.CLICK,onclick);
pink.addEventListener(MouseEvent.CLICK,onclick);
function onclick(event:MouseEvent){
if(event.target==red)
{myColor.color=0xff0000}
else if(event.target==green)
{myColor.color=0x99ff33}
else if(event.target==blue)
{myColor.color=0x00ccff}
else if(event.target==orange)
{myColor.color=0xffcc33}
enter code here
else if(event.target==yellow)
{myColor.color=0xffff66}
else if(event.target==pink)
{myColor.color=0xff99ff}
else
{myColor.color=0x666666}
square.transform.colorTransform=myColor
}
mc1.addEventListener(MouseEvent.CLICK, colorChange);
function colorChange(event:MouseEvent)
{
mc1.transform.colorTransform=myColor;
}
// upto here the code works fine but from below i get a duplicate fuction error which i don't know how to fix.
// the idea is to add more movie clips so i can change their colors just like i can do for mc1.
1021: DUPLICATE FUNCTION DEFINITION "ERROR"
mc2.addEventListener(MouseEvent.CLICK, colorChange);
function colorChange(event:MouseEvent)
{
mc2.transform.colorTransform=myColor;
}
Push all movieclips into array and then add eventlistener to all of them like this:
var mcArray:Array=new Array();
mcArray.push(mc1,mc2);
for (var i:int=0;i<mcArray.length;i++)
{
mcArray[i].addEventListener(MouseEvent.CLICK,colorChange);
}
And add only one colorChange function like this:
function colorChange(event:MouseEvent)
{
e.currentTarget.transform.colorTransform=myColor;
}

Adobe Flash Pro CS6 movie looping after adding code to actionpanel

i have got a problem and cannot figure out. Everything is fine when i test the scene, i have added stop(); to my movie clip timeline and everything is fine until no code is added to the main stage. As soon as i start adding code to the stage, it starts looping? Because of this i'm stuck with a problem and cannot even develop further, because even mouse click events wont work of that looping... The code i am trying to add is just a simple move layer off stage after click on play button:
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
introScreen.play_btn.addEventListener(MouseEvent.CLICK, clickAway);
function clickAway(event:MouseEvent):void
{
moveScreenOff(introScreen);
}
function moveScreenOff(screen:MovieClip):void
{
//Move the screen off...
var introTween = new Tween(screen,"x",Strong.easeInOut,screen.x,(screen.width)*-1,1,true);
//When the motion has finished...
introTween.addEventListener(TweenEvent.MOTION_FINISH, tweenFinish);
function tweenFinish(e:TweenEvent):void
{
trace("tweenFinish");
//Establish the game state...
gameState = STATE_INIT_GAME;
trace(gameState);
//Fire off the gameLoop function at the frame rate of the movie...
addEventListener(Event.ENTER_FRAME, gameLoop);
}
}
The reason your animations are looping continuously is because you have errors in your code.
Access of undefined property gameState.
Access of undefined property STATE_INIT_GAME.
Access of undefined property gameState.
Access of undefined property gameLoop.
You are trying to reference members that haven't been created yet or don't exist. Your main timeline starts at frame 1 with the code you referenced trying to access those variables and the gameLoop method. You need to setup the variables in the first frame to allow them to be referenced. i.e. under your import statements:
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
var gameState:String;
const STATE_INIT_GAME:String = "GAME_INIT";
then you need to add the gameLoop function:
function gameLoop(e:Event):void {
trace('game loop running');
}
If you don't want those variables and that function setup there then you need to go to the frame using gotoAndStop or gotoAndPlay where those functions and variables can be declared and/or initialized, and stored into memory. Then they will be accessible.

getURL in AS3, how to?

Hello I have not used flash in years, and need to use some old tracking code in my new AS3 banner. I noticed that in 3.0 you can't place actionscript on objects themselves, just on the timeline.
I need to convert this As2 script which i would normally have on a button labeled 'my_button'
on (release) {
getURL (_level0.clickTag, "_blank");
}
What is the equivalent code snippet to use on the timeline for my button labeled 'my_button'?
This is Google's clickTag suggestion:
import flash.events.MouseEvent;
import flash.net.URLRequest;
// ......
someButton_or_displayObject_to_receive_mouseClick.addEventListener(MouseEvent.CLICK,
function(event: MouseEvent) : void {
flash.net.navigateToURL(new URLRequest(root.loaderInfo.parameters.clickTAG), "_blank");
}
);
I saw a few diffrent examples, but none of them were identical to the method I use;
This is a full version, just copy and past and add in your URL AS3
import flash.events.MouseEvent;
import flash.net.URLRequest;
// add event listener to listen for "btnOpen" click
btnOpen.addEventListener(MouseEvent.CLICK,openFuction);
// add our openFuction
function openFuction(e:MouseEvent){
var openPage:URLRequest=new URLRequest("https://mysite.co.uk")
navigateToURL(openPage,"_blank");
}
There's another way, as well, which doesn't necessarily rely on the use of the ExternalInterface class. You could also try something like this (assuming your object on the stage has an instance name of "mybtn_mc":
mybtn_mc.addEventListener(MouseEvent.CLICK, openWebpage);
//
function openWebpage(e:MouseEvent):void {
var my_url:URLRequest = new URLRequest("http://stackoverflow.com/questions/15580069/geturl-in-as3-how-to/15639569");
flash.net.navigateToURL(my_url, "_self");
}
// if you want the object to act like buttons do in AS2
// with the handcursor effect when you mouse over them,
// you would include the following lines:
mybtn_mc.buttonMode = true;
mybtn_mc.useHandCursor = true;
This is written in timeline style, which is not something I approve of. But I sense you're not even close to ready to earning about Classes and how they work.
myButton.addEventListener(MouseEvent.CLICK, openWebpage);
function openWebpage(e:MouseEvent):void {
if (ExternalInterface.available) {
var callReturn:String = ExternalInterface.call('function(){window.open("http://www.yourURL.com", "_blank", "top=0,left=0,width=800,height=600");}');
}
}
Note that you should not be trying to reach outside the scope of the current MC, but how to do something else is beyond the scope of this answer har har. If interested, do a search on Dependency Injection.

AS3 Loader keeps reloading same swf over and over

I have a flash animation made on the main timeline of the SWF with a couple of layers, some functions and some keyframe labels. For example, i have a movieclip of a star that come across the screen and then triggers a dispatchEvent for the main timeline to go to frame label "next".
Here is a sample of the actionscript used on the main timeline :
Stars.addEventListener("fadeInTitle",_fadeInTitle);
function _fadeInTitle(e:Event):void {
Title.gotoAndPlay("fadeIn");
Stars.removeEventListener("fadeInTitle",_fadeInTitle);
}
stop();
That SWF alone works perfectly. Problem comes when I try to load this SWF into another one.
What happens is the loader keeps reloading the SWF over and over, overlapping them and the actionscript that's on the main timeline of the loaded SWF is ignored, the timeline plays continuously. Here is the code i use to load the SWF :
import flash.net.URLRequest;
import flash.display.Loader;
import flash.events.Event;
import flash.events.ProgressEvent;
function startLoad(){
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest("Fly.swf");
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
mLoader.load(mRequest);
}
function onCompleteHandler(loadEvent:Event){
addChild(loadEvent.target.content);
}
function onProgressHandler(mProgress:ProgressEvent){
var percent:Number = mProgress.bytesLoaded/mProgress.bytesTotal;
}
startLoad();
There's nothing special there. Just a simple loader.
I have found a workaround by putting the entire animation inside one main movieclip and put that movieclip on the main timeline (one keyframe, one layer, no actionscript) and then load it. That way it works fine but it feel more like a patch than a solution. I would really like to know why it's bugging when you try to load an external SWF that use the main timeline with multiple layers, keyframes and actionscript.
Any help/hint will be greatly appreciated.
Thanks a lot for reading.
m
First take the loader instantiation out of a function, it is not necessary. Second, kill your listeners in the onComplete function. Third, if this loader code is on the timeline of your loader shell, make sure that there is not more than one frame, or if there is (not sure why there would be though) place a stop on the frame containing the loader code. Or even better, use a Document class to contain your loader code rather than putting it on the timeline. My best guess is you were calling startLoad() over again somehow. Also, make sure you have the flash debug player installed so you are getting proper error reporting when viewing this in a browser.
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest("Fly.swf");
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgressHandler);
mLoader.load(mRequest);
function onCompleteHandler(loadEvent:Event)
{
mLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onCompleteHandler);
mLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgressHandler);
addChild(loadEvent.target.content);
}
function onProgressHandler(mProgress:ProgressEvent)
{
var percent:Number = mProgress.bytesLoaded/mProgress.bytesTotal;
}