Actionscript 3 - can't open multiple navigateToURL() instances at the same time - actionscript-3

I am new to AS3, I want to open multiple browser tabs with flash.
I'm trying to simply start multiple instances of navigateToURL().
for each (var str:String in arrayofrequests)
{
[...]
try { navigateToURL(request, "_blank");}
[...]
}
but only the last instance of navigateToURL gets executed in the browser.
I searched online and someone pointed out callLater could solve this issue.
But every time I try to use callLater I get
Error: Call to a possibly undefined method callLater.
I analyzed adobe documentation here: http://help.adobe.com/en_US/flex/using/WS2db454920e96a9e51e63e3d11c0bf69084-7b06.html
All objects that inherit from the UIComponent class can open the callLater() method.
How I do this? I tried to change my code to something like this
public class Main extends UIComponent
but it isn't working.

To start, UIComponent class is the base class for all visual components used in Flex ( like Label, Progressbar, ...), but I think that your are using Flash, so it's not the good way.
Really I don't know why you want to open many urls in the browser in the same time ( and I think that your final user may be will not like that ), but you have to use some intervals between every navigateToURL() calls using a Timer object for example :
var urls:Array = [
'http://www.wikipedia.org',
'http://www.ubuntu.com',
'http://www.stackoverflow.com'
];
var timer:Timer = new Timer(300, urls.length);
timer.addEventListener(TimerEvent.TIMER, onTimer);
function onTimer(e:TimerEvent):void {
navigateToURL(new URLRequest(urls[timer.currentCount - 1]), '_blank');
}
timer.start();
Hope that can help.

Related

Removing a child of a video class called from a private function

I'm making a quiz type animation for work where on clicking an answer it plays a short animation FLV file relating to what you picked. As everything I read points towards AS3 being OOP I decided to make a MovieClip containing an FLV player and linked it to an AS3 file called FLV_Player.as. That way I can create a new instance of the FLV_Player everytime I need to play a video. Here is the code in that file which seems to work fine:
package
{
import fl.video.VideoEvent;
import flash.events.VideoEvent;
import flash.display.MovieClip;
public class FLV_Player extends MovieClip
{
public function FLV_Player(NextVideo:String)
{
animation_player.source=(NextVideo);
animation_player.addEventListener(VideoEvent.COMPLETE, vcompleted);
}
private function vcompleted(e:VideoEvent):void
{
nextFrame();
}
}
}
Now in the DocumentClass.as file I have this code:
private function NewVideo(videoname:String)
{
var nextvideo:FLV_Player = new FLV_Player(videoname);
addChild(nextvideo);
nextvideo.x = 0;
nextvideo.y = 0;
}
So when you click a button, go to the next frame or whatever the prompt is, it calls the NewVideo function and passes the name of whatever video is to be played next.
NewVideo("Introduction.flv");
Now I'm sure I'm going to run in to other issues later down the line as I really have no idea whether anything I've done is how it should be done, but the only issue I seem to be having at this point in time is removing the video and going to the next (or previous) frame to answer another question. I tried:
nextFrame();
removeChild(newVideo);
But it didn't work. Well, it may have gone to the next frame but with the video taking up the whole window it's hard to see if it did or not.
So how do I remove the video I've created? The main issue seems to be that because I had to create a new instance of the FLV_Player class in a private function the child is defined locally "var", rather than "public" or "private" var so I can't reference it again. It tells me that you can only create a "private var" from within the document class but if I make it there it will create the class on load rather than from the function when I'm ready to pass the video name parameter to it. At load I don't know what video I need it to play?
removeChild() must be called from the same object in which it was added. In this case, your DocumentClass. What you're trying to do now is telling an FLV_Player to remove itself, which won't work due to several reasons and bugs in your code.
The correct way to do things would be to have the FLV_Player object dispatch a custom event that your DocumentClass listens for. You need to create a new class which inherits from Event to create your custom event. I'd call it "PlayerEvent". In DisplayClass function you'd do this:
nextVideo.addEventListener(PlayerEvent.PLAYBACK_FINISHED, onPlaybackFinished);
addChild(nextVideo);
Then you need to create the onPlaybackFinished method:
private function onPlaybackFinished(event:PlayerEvent):void {
nextVideo.removeEventListener(PlayerEvent.PLAYBACK_FINISHED, onPlaybackFinished);
removeChild(nextVideo);
}
Inside the FLV_Player class, the vcomplete function should change to:
dispatchEvent(new Event(PlayerEvent.PLAYBACK_FINISHED));
Alternately, you could pass a pointer of the DocumentClass to the FLV_Player object, but this is very messy, can cause serious problems and not at all in the spirit of OOP. But it's a quick fix if you want to be lazy.
Events are an extremely important part of Actionscript 3 and I recommend you read up on them. Here's some good references:
http://www.adobe.com/devnet/actionscript/articles/event_handling_as3.html
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7fca.html
http://www.blog.mpcreation.pl/actionscript-3-0-basics-custom-events-part-1/
I think you're right that your first problem is simply how to reference the new video, so to expand on my comment a bit: You can declare a variable without also assigning a value, so you don't need to have var nextvideo within your NewVideo function. With a class level variable instead, you can then reference whatever you set nextvideo to when you want to remove the video:
public class DocumentClass {
private var nextvideo:FLV_Player;
private function NewVideo(videoname:String)
{
nextvideo = new FLV_Player(videoname);
addChild(nextvideo);
}
private function removeVideo():void
{
removeChild(nextvideo);
nextvideo = null;
}
}

How can I give flash stage instances unique properties in Flash Professional to pass to AS3 script?

I've started building a rough game engine framework in Flash Professional and I'm curious how I can create objects in the Flash library that I'm able to drag onto the stage and assign properties that are accessible from AS3.
Example:
I want to create a switch object (e.g. a light switch), so that when the player interactes with it, it triggers something specific in code such as a light in the room turns on.
I understand that Flash has built in UI components that you can define properties within the Flash Professional environment (see image below), and I'm wondering if there's a way to create my own custom style components so that I can essentially have my level file open in flash (.fla) and then drag a switch component from my library, and type in some information such as what light it is controlling, and any other information I want.
(above is an example of the type of parameter control I'm looking for)
I've read a bit about extending the flash UIComponent class but I feel that that's not the right approach because it's overkill for what I want. All I want is to pass some basic parameters from a library stage instance into AS3. I do not want to pass data via the instance name because this seems very messy if I want to have more complex interaction.
Thanks!
I would create a "switch" movie clip and export it to actionscrip, same with a "light" movie clip. The in the main class .as file I would inset them into the stage, using addChild (clips) and then add a click listener to the "switch" movie clip to control the "light".
This can be easily done.
Component(s) are wrong approach in my opinion.
Firstly you would want to setup Actionscript linkage / label your Library item.
In Library Panel.
- Right Click on "yourMC" >> click "Properties".
- In Properties dialog Tick "Export for Action Script"
- Then Name your Class eg "yourMC_Class"
now MC is ready to be referenced in your code.
next you would want to Dynamically add your "yourMC" from library to stage.
which can be done like such.
// first reference library item
var yourMC_ref:yourMC_Class = new yourMC_Class();
// Then load dynamic mc item into var
var your_MC_OBJ = yourMC_ref;
// then add your MC to stage.
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
in a nutshell that's how I add library items to stage.
Obviously thats the basic function / code.
In a project I would have all code in an external class, in which case you would just set vars as public vars
public var yourMC_ref:yourMC_Class = new yourMC_Class();
public var your_MC_OBJ = yourMC_ref;
and the last 3 lines of code into a public function
public function ADD_First_MC()
{
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
}
Now 'your_MC_OBJ' can be used in more complex ways.
eg. to create a light switch there are many options depending on how you need to approch functionality.
eg. Apply a different MC library item to "your_MC_OBJ"
play specific frame within MCs.
However If it was me I would just use mouse function to switch light on or off using addChild removeChild.
eg.
public var LightON = 0;
public var yourMC_ref:yourMC_Class = new yourMC_Class();
public var your_MC_OBJ = yourMC_ref;
then create a public function that handles on / off events
public function LightON_OFF()
{
if(LightON == 1)
{
this.addChild(your_MC_OBJ);
your_MC_OBJ.x = 200;
your_MC_OBJ.y = 100;
}
if(LightON == 0)
{
this.removeChild(your_MC_OBJ);
}
}
Hope this helps.
So, for what you want, while it may not be the best way to do what you want, I understand it's your experience you are constructing.
Use components, yes...in the following way (the most simple one):
Create a Movie Clip
Right-click it in library
Click on "Component Definitions"
Add a property, set a name, a variable name (var test, for this matter) and a default value
Click OK
Open your movie clip
Open code for the first frame and declare the variable without an initial value (var test:String;)
Trace it's value ( trace( test ); )
Go back to the stage root
Drag and drop the item from library to stage
Test it (Cmd/Ctrl + Enter) (maybe it will print null, dunno why, it ignores the default value sometimes)
Select your component on stage
Open the properties panel (Windows > Properties)
Go to Component Parameters on this panel and change the property value
You should see the value traced on console
And, I think, like this you can use properties from components for what you want, like using a String and getting the controlled mc by its name.
Good luck
I think what people are trying to say is that you can have the whole thing is data driven, and so you can combine the IDE with the data to come up with your final game.
But consider this ... it might be what you want.
If you have, for instance, a BaseSwitch Class:
public Class BaseSwitch extends MovieClip {
private var _lightName:String;
private var _light:Light;
public function get lightName():String {
return lightName;
}
public function set lightName(value:String):void {
if (value != _lightName) {
_lightnName = value;
//Note I don't advocate having children reach into their parents like this,
//but you sound like you don't want the parent involved in the process, so
//this is one way you could do it.
if (parent.hasOwnProperty(lightName) && parent[lightName] is Light) {
_light = parent[lightName];
} else {
trace('Could not find light', _lightName);
}
}
}
//other code to listen for gestures and operate the light
}
Now, when you want a switch to operate a specific light name, create a library instance and set its base class to BaseSwitch. When you close the dialog where you set the base Class, you'll notice that it gives you a dialogue that it couldn't find the Class in the Class path and one will be generated. You're going to replace it with a Class that sets the lightName. Create a new AS3 Class in the root directory with the same name as your library instance. It should look something like this:
public class SpecificSwitch {
public function SpecificSwitch() {
super();
lightName = 'theSwitch';
}
}
Other possible choices involve having the parent Class match up instances of switch with instances of light based on name, so if it finds a light1 and a light1Switch, it either gives a reference to the light to the switch or it simply sets up a mapping in its own event listening system.

multiple instance of class in as3

i have a function to load sound in main document class in as3,this function accept input link and begin to load this path for example same function :
private function loadSound(url:String):void{
var req:String = 'sound/'+url+'.mp3'
sound_path = new URLRequest(req)
main_sound = new Sound()
main_sound.load(sound_path)
main_sound.play()
}
when this function call, sound object multiple start playing,how i solve this problem for play only sound class in this time ?
Place this at beginning of your loadSound() function:
flash.media.SoundMixer.stopAll(); //Stops all music already playing
If you have this code in a keyframe make sure you are calling stop() to prevent it from executing the code over and over.
If you have it in a class file (.as) it sounds like it is getting called twice

AS3 event across multiple files

I'm migrating from AS2 to AS3 and have this problem..
In my project I used main document file, which could load multiple nested animations as a separate files. In the main document I had a global function, for example:
_global.onAnimationEnd(mc:MovieClip){...}
and in animations (could be nested) I just called it like:
onAnimationEnd(this);
I'm new with AS3 but somehow thing that the proper way in AS3 is to use Event system, but I have problems to do it. Is there someone who can help with such an easy(AS2) issue?
The way that AS3 handles events is quite different to the AS2 approach. In AS3 events bubble up the object hierarchy and then back down to the originating object. If you have objects further up the hierarchy that are required to respond to an event it is necessary to set up event listeners on the recipient objects to handle the event as it bubbles.
Colin Moock's book Essential ActionScript 3.0 published by O'Reilly deals with it comprehensively. Not much help if you need a quick fix right now though…
Finally I'm using this approach:
I'm using custom event like:
package com.oldes {
import flash.events.Event;
public class GameEvent extends Event {
public var data:Object;
public static var ANIMATION_END = "onAnimationEnd";
public function GameEvent(
type:String,
data: Object,
bubbles:Boolean=true,
cancelable:Boolean=false
){
super(type, bubbles, cancelable);
this.data = data;
}
override public function clone():Event {
return new GameEvent (type, data, bubbles, cancelable);
}
}
}
In my deep nested animations I replaced:
onAnimationEnd(this);
with:
import com.oldes.GameEvent;
dispatchEvent(new GameEvent(GameEvent.ANIMATION_END,{anim: this}));
Using clasic listeners to deal with the cached event.
EDIT: the external file with animations must be properly loaded into the correct context, but that's another AS3 story.

HTTPService/ResultEvent with Flex 3.2 versus Flex >= 3.5

through a design decission or what-so-ever Adobe changed the content of the ResultEvent fired by a HTTPService Object.
Take a look at following example:
var httpService:HTTPService = myHTTPServices.getResults();
httpService.addEventListener(ResultEvent.RESULT,resultHandler);
httpService.send();
/**
* Handels the login process
*/
function resultHandler(event:ResultEvent):void
{
// get http service
var httpService = (event.target as HTTPService);
// do something
}
It works like a charm with Flex 3.2. But when I try to compile it with Flex 3.5 or Flex 4.0 event.target as HTTPService is null.
I figured out that event.target is now an instance of HTTPOperation. That is interesting because I can't find HTTPOperation in the langref. However, I think what Flash Builder's debugger means is mx.rpc.http.Operation.
The debugger also shows that event.target has a private attribute httpService which is the instance I expected to get with event.target. But it's private, so event.target.httpService doesn't work.
If I only want to remove the EventListener I can cast event.target as EventDispatcher. But I need to use methods from HTTPService.
So: How can I get the HTTPService instance from the ResultEvent?
Any help would be appreciated. Thanks!
J.
It is useful to go through the source if you get into this. On OS X the rpc classes are here: /Applications/Adobe Flash Builder Beta 2/sdks/3.4.1/frameworks/projects/rpc/src
Inside mx.rpc.http.HTTPService there is indeed an inner-class named HTTPOperation.
It extends mx.rpc.http.AbstractOperation which in turn extends mx.rpc.AbstractOperation. Inside AbstractOperation is a getter method get service which looks to return what you need.
Since HTTPService is an inner-class it is effectively private so you'll need to cast to an AbstractOperation (either mx.rpc.http.AbstractOperation or mx.rpc.AbstractOperation).
So something like:
function resultHandler(event:ResultEvent):void
{
// get the operation
var operation:AbstractOperation = AbstractOperation(event.target);
// get http service
var httpService:HTTPService = HTTPService(operation.service);
}
edit: I take it back! Looks like Adobe is sending null for the service when it calls the super when constructing the HTTPOperation. The HTTPService is therefore only cached in the private variable httpService. I have no idea why they hide it from you but it looks like you'll have to keep your own reference around.
I solved this problem for myself.
There are some properties in HTTPService that are available from AbstractOperation. For example, I use property request which is an Object:
myService.request["service"] = myService;
And later, when I get Event which has HTTPOperation in event.currentTarget, I get my HTTPService in such way:
var eventService : HTTPService = HTTPService( AbstractOperation( event.currentTarget ).request["service"] );