Adding the same function to multiple buttons in Actionscript 3.0 - actionscript-3

I am trying to add the same button function to 2 different symbols in Flash. One is the logo and the other is text that I converted to a symbol that will show itself during the end scene.
I don't understand what I am doing wrong, but I am extremely new to Actionscript & Flash.
My code looks like this:
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.net.navigateToURL;
import flash.net.URLRequest;
myButton, txtButton.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
function onClick(e:MouseEvent):void{
navigateToURL(new URLRequest("http://www.true.land"), "_blank");
}
But I am getting this error:
Attempting to launch and connect to Player using URL
C:\Users\Angela\Desktop\ASU\GIT 314\Assignment
7\AngelaRogers_Assignment7.swf [SWF] C:\Users\Angela\Desktop\ASU\GIT
314\Assignment 7\AngelaRogers_Assignment7.swf - 351066 bytes after
decompression TypeError: Error #1009: Cannot access a property or
method of a null object reference. at
Button/frame1()[Button::frame1:7]

You must write it twice - once for each button, starting with only it's name: child.addEventListener. There is no shortcut to add the same for two objects at once.

You can write a shortcut function to do this easily enough. (As pointed out by others, your comma is what is causing the error). This I believe is more what you're after: (especially if you keep adding more buttons).
import flash.events.MouseEvent;
import flash.display.MovieClip;
import flash.display.SimpleButton;
import flash.net.navigateToURL;
import flash.net.URLRequest;
addClick(myButton, txtButton); //you can add as many items as you want as parameters
function addClick(...buttons):void {
//the ...buttons parameter is known as the '...rest' parameter, and is an array of all the parameters passed to the function
for each(var btn:Sprite in buttons){ //loop through all the items passed in and add the listener
btn.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);
}
}
function onClick(e:MouseEvent):void{
navigateToURL(new URLRequest("http://www.true.land"), "_blank");
}

Related

Why can't I remove this Movieclip?

I have a TouchEvent function onTouch inside the constructor function of a item_Potion class that gets run when a Movieclip is touched. This function goes through a series of unrelated checks and then in the end it is supposed to remove itself (the Movieclip).
At the end of the onTouch function it is supposed to remove itself by doing the following:this.parent.removeChild(this);
However, this does not work.
I get the following error message:
TypeError: Error #1010: A term is undefined and has no properties.
at Function/item_Potion/$construct/onTouch()[E:\Clients\org\tcdsb\ZenithsReach\item_Potion.as:56]
at runtime::ContentPlayer/simulationSendTouchEvent()
at runtime::SimulatedContentPlayer/clientSocketDataHandler()
The line it's reffering to for the error message (Line 56) has the following:
this.parent.removeChild(this);
My imports:
` import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
import flash.display.*;
import flash.events.TouchEvent;
import flash.net.dns.AAAARecord;
import flash.ui.Multitouch;
import flash.ui.MultitouchInputMode;`
I know the problem is not with the other portions of my code because I have tried switching this line out with visible = false; and I get no errors. Therefore, I am certain that the issue is with the way I am removing the MovieClip, and that is where I need help.
Similiar Sources I have tried that do not work:
How to make a MovieClip remove itself in AS3?
parent is undefined in your example, hence the error "a term is undefined...".
You can avoid the error by wrapping your code in:
if (parent) {
parent.removeChild(this);
}
But based on your comment providing [object global] is sounds like you might actually want something like:
event.currentTarget.parent.removeChild(event.currentTarget);
Which would remove the object that the touch event listener was added to.

How to convert a two-file preloader and game swf with Document class into single swf?

I have a game that I've made that runs in two files, one the preloader and one the swf. When I use these two files together they work fine, however some flash portals require only one SWF, so I'm trying to find the shortest-path way to convert it to use only one.
The game swf uses a Document Class that includes the package, class constructor, and tons of functions, and runs fine. I have lots of movieclips on the stage that I refer to in my code. The code is something like this (abridged):
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
...
public class Game extends MovieClip {
var EnemyArray:Array;
var HeroArray:Array;
...
public function Game() { // class constructor
EnemyArray = new Array();
addEventListener(Event.ENTER_FRAME,onEnterFrame);
mainRestartButton.addEventListener(MouseEvent.CLICK, RestartLevel);
...
}
public function KeyPressed(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.SPACE)
{
attack();
...
}
} // End of class
} // End of package
I also have another swf, my preloader, which has the following code in frame 1:
import flash.display.Loader;
import flash.net.URLRequest;
import flash.events.ProgressEvent;
import flash.events.Event;
var myLoader:Loader = new Loader();
myLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoading);
var myURL:URLRequest = new URLRequest("Game.swf");
myLoader.load(myURL);
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
function onLoading(event:ProgressEvent):void {
var loaded:Number = event.bytesLoaded / event.bytesTotal;
percent_txt.text = "Loading: " + (loaded*100).toFixed(0) + "%";
}
function onComplete(event:Event):void {
myLoader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onLoading);
myLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onComplete);
this.addChild(myLoader);
}
I've been through the gamut of solutions online and none of them seem to work with the way that my code is set up, such as: How to create Preloader in AS3
I tried his option 1 by taking all the code in my Document Class other than the package and constructor and pasted it into frame 2. However it returns "Error #1009: Cannot access a property or method of a null object reference." for any references to items on the stage, such as:
mainRestartButton.addEventListener(MouseEvent.CLICK, RestartLevel);
As he mentions, "This works well if you organized your project in a way that the most of the assets (images, etc) are in the Flash IDE Library and are not loaded on the first frame (you can check that in each library item's properties)." My project is NOT organized in such a way.
What is the easiest way for me to reorganize my FLA/code so they can have a preloader in a single swf?
Thanks so much for your time and help!
I use FlashDevelop (no FLAs) so I'm not sure if it'll work for you but I use the solution described here.

flashfirebug As3 console timer or setInterval not working

i have tried to use a timer in the as3 console from FlashFirebug addon but it doesn't work (have tried several combinations). The timer code was this:
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Sprite;
var myTimer = new Timer(1000, 2);
myTimer.addEventListener(TIMER, timerHandler);
myTimer.start();
function timerHandler(event:TimerEvent){trace("timerHandler: ");}
//but it gives this error:
Error #1034: Type Coercion failed: cannot convert r1.deval.rt::FunctionDef#50ef781 to Function.
//also have tried with setInterval with this code:
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Sprite;
import flash.utils.setInterval;
function d(){trace("cc");}
setInterval(d, 2000);
//but console error says:
Error: Call to a possibly undefined method.
//probably need to import something. tried tho import "import flash.utils.setInterval;" but gives this error:"Error: You must import the class before being able to instantiate it. Ex. import flash.display.MovieClip;"
Can you help me on This? timer or setInterval functions?
Thanks,
John
I'm not sure about the error message you're getting, but you do have an error in your code at the point at which you assign the event listener for your timer. You need to access the event name constant from the TimerEvent class like so:
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.display.Sprite;
var myTimer = new Timer(1000, 2);
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
myTimer.start();
function timerHandler(event:TimerEvent){trace("timerHandler: ");}
There's a decent explanation here on the advantages of using the ActionScript 3.0 Timer class over setInterval.
Well, looks like there is no way to achieve this. FlashFirebug uses D.eval library and I can't find that it supports timers or intervals right now.
I'm not sure you've sorted it yet but it looks like:
var num:int = setInterval(d, 2000);
and if you import import flash.utils.clearInterval; you can stop it like:
clearInterval(num)
The problem is on this line:
myTimer.addEventListener(TIMER, timerHandler);
It should be:
myTimer.addEventListener(TimerEvent.TIMER, timerHandler);
// add this ^^^^^^^^^^^
This is quite old. But answering it to help anyone in the future.
FlashFirebug 4.8.0 which is still on the approval queue (at the time of answer) should enable you to inject an SWF file inside the running SWF.
That would allow you to use full AS3 capabilities when you hit limitations with the console.

Scrollbar not working with TLF text with dynamic content in ActionScript 3

I'm creating a simple Flash project with Flash CS5 and ActionScript 3.
What I want to do is that I want to dynamically update a TLF text container with given source and destination, something like loadData(text_placeX, "markup.xml"); anywhere that I want.
It's working like a charm, but the problem is I can't use any scroll-bar for my text. I have added a UIScrollBar to text container and it's working with the default text that I've putted into text container, but when I update container with my data it's not working. What am I missing?
Another question is that how I can empty my text container before loading new data in it?
My code is:
import fl.text.TLFTextField;
import flash.display.Loader;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.text.TextFieldAutoSize;
import flashx.textLayout.container.ContainerController;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.conversion.TextConverter;
import fl.controls.ScrollBar;
var ldr:URLLoader = new URLLoader();
var flow:TextFlow = new TextFlow();
function loadData(text_place, fileURL:String):void {
text_place.border = true;
ldr.dataFormat = URLLoaderDataFormat.TEXT;
ldr.addEventListener(Event.COMPLETE, function(evt:Event){ ldr_complete(text_place) }, false, 0, true);
ldr.load(new URLRequest(fileURL));
ldr.addEventListener(IOErrorEvent.IO_ERROR, loadError);
}
function ldr_complete(text_place:TLFTextField):void {
ldr.removeEventListener(Event.COMPLETE, ldr_complete);
ldr.removeEventListener(IOErrorEvent.IO_ERROR, loadError);
initText(text_place, ldr.data);
}
function loadError(e:IOErrorEvent):void {
trace("Error loading an external file. The server may be busy. Try refreshing the page.");
}
function initText(text_place:TLFTextField, fileContent):void {
flow = TextConverter.importToFlow(fileContent, TextConverter.TEXT_FIELD_HTML_FORMAT);
flow.flowComposer.addController(new ContainerController(text_place, text_place.width, text_place.height));
flow.flowComposer.updateAllControllers();
}
UPDATE: When I skip using of initText function contents and instead I use text_place.tlfMarkup = fileContent; it works; but my option on TextFlow is missing. And also I was missing "update scrollbar" after putting content in text-field.
I think this line may be the problem:
ldr.addEventListener(Event.COMPLETE, function(evt:Event){ ldr_complete(text_place) }, false, 0, true);
You have an anonymous function here (function(evt:Event){...) which passes the object text_place to the function ldr_complete(). However, you do not have access to text_place, since it is a variable declared within a different scope. If you make the function into a named one, you will not assume that you have that access. E.g.,
function loadCompleteHnd(evt:Event):void{
[...]
}
However, you still have to gain access to the object in text_place. So, you can make text_place a class-level (global) variable, and set that variable whenever. But that may run the risk of creating a race condition -- if you have a slow load, you might be trying change that object from two places at once.
Another option is to create an entirely new Event which extends the Event.COMPLETE setup. At that point, you can create another parameter for the Event.COMPLETE listener to use. This is complicated, and a bit of a learning curve, but it makes events more versatile.
In either case, you may want to set up a flag that tells you whether something else is editing the same object. It's not foolproof, but it can save some headaches.

keyboard input with actionscript

I'm writing in pure actionscript in notepad with flex as a compiler. Here's the code I have
package
{
import flash.display.*;
import mx.core.*;
import flash.events.*;
import mx.collections.*;
import flash.geom.*;
import mx.controls.*;
import flash.text.*;
import mx.events.*;
import mx.styles.*;
import mx.containers.*;
public class MAIN extends Sprite
{
public var APPLICATION:Application = Application(Application.application);
public var FRAME:int = 0;
public function MAIN()
{
addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
STEP();
}
public function STEP():void
{
FRAME ++;
STEP();
}
public function keyDownHandler(event:KeyboardEvent):void
{
var keyDownText:TextField = new TextField();
keyDownText.text = "Key code: " + event.keyCode;
this.addChild(keyDownText);
}
}
}
What I want is for whatever key I happen to press to be drawn on the screen (though actually I think it would only be the ascii number it corresponds to but that doesn't matter). Right now though everything's just blank. Another thing is because I'm not using any mxml I don't know if i've established the game loop correctly so let me know if that needs to be fixed.
Try
stage.addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
instead of
addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
Since your Sprite doesn't have a visible area, it will not receive keyboard or mouse input.
Also the STEP() function will cause a stackoverflow because it's infitely recursive.
If you want a main loop that gets called periodically, try using an ENTER_FRAME handler or a Timer.
Something like this:
public function MAIN()
{
addEventListener(KeyboardEvent.KEY_DOWN,keyDownHandler);
addEventListener(Event.ENTER_FRAME,STEP);
}
private function STEP(e:Event):void {
FRAME++;
}
To stop it, do this:
removeEventListener(Event.ENTER_FRAME,STEP);
Not sure why you are using ALL CAPS for some methods and variables. Although it's not a language requirement, all caps are generally reserved for constants. Method names use camelCase. And types use PascalCase (like camelCase, but the first letter is capitalized). So your class would be Main, FRAME would be fram, STEP would be step, etc. You're better off sticking to these common naming schemes, I think.
And another thing. You probably shouldn't be creating a new TextField instance everytime you want to output some text. One textfield will do it in your case, I think. So create and addChild the textfield on some kind of init method that you call when you start your class and then just use the text property of this textfield to write your messages.