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.
Related
I'm very new to AS3 and I'm trying to learn by experimenting in flash, by making a simple 2D farming game with very simple code.
I've made one crop field out of 6 that works, which is a movieclip with different frames for each fruit growing. For example, frame 1-5 is a strawberry growing where frame 5 is when it's ready to be picked, and then 6-10 is of carrots, etc
Is there a way for me to make it so that I don't have to write the exact same code for the next crop field, and instead change the variables in this code depending on which crop field you click on?
Here's an example of the code
if (field1.currentFrame == 1)
{
field1.nextFrame();
infoText.text = "You've watered the crop. Let's wait and see how it turns out!";
function plantStrawberry():void
{
field1.nextFrame();
if (field1.currentFrame == 5)
{
clearInterval(strawberryInterval);
}
}
var strawberryInterval = setInterval(plantStrawberry,5000);
}
pls no judgerino, as said, I'm very new to AS3, lol.
There are a few ways to go about being DRY (don't repeat yourself) with your code in this scenario. The best way, would be to learn to use classes. Classes are blueprints, and are made for these very scenarios.
Here is an example of a simple class to do what you'd like. In Flash/Animate, go to file, then new, then 'ActionScript 3.0 Class' - give it a name of Crop.
In the document that comes up, there should be some basic boilerplate code. Everything should wrapped in a package. The package tells flash where to find this class - so this example, leave it as is (just package {) and save this file in the same folder as your .fla. All functions need to be wrapped in a class declaration, this should be generated for you based off the name you put in (Crop). Next you'll see one function, that has the same name as the class. This is called a constructor, and this function runs whenever you create a new instance of this class. Since classes are blueprints, you create instances of them that are objects - those objects then get all the code you put in this class.
So, to start, you should have this:
package {
public class Crop {
public function Crop() {
// constructor code
}
}
}
Let's go ahead and put your code in. See the code comments for details:
package {
//imports should go here
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.utils.Timer;
//lets make this class extend MovieClip - that means it will be a MovieClip in addition to everything else you add below
public class Crop extends MovieClip {
//instead of setInterval, use a timer - it's easier to manage and cleanup
//in class files, variables and functions have access modifiers, that's what the public and private words are about
//private means only this class can ever use the var/function
private var timer:Timer;
public function Crop() {
//initialize the timer - have it tick every 5 seconds, and repeat 4 times (to move you from frame 1 - 5)
timer = new Timer(5000, 4);
//listen for the TIMER event (which is the tick) and call the function 'grow' when the timer ticks
timer.addEventListener(TimerEvent.TIMER, grow);
}
//a function that starts the timer ticking
public function startGrowing():void {
timer.start();
}
//this function is called every timer tick.
private function grow(e:Event):void {
this.nextFrame(); //go to the next frame of your crop
}
}
}
Save the file. Now that you have this class, you need to attach it to your library assets so they all get this functionality.
In the library panel, for each of your crop objects, right click (or ctrl+click on Mac) and go to properties. In the properties, click advanced, and give it a unique class name (for instance Strawberry). Then in the base class field, put Crop (the class we just made). Repeat for the others.
Now on your timeline, when you want a crop to start growing, you can do:
field1.startGrowing(); //assuming your instance `field1` is one of the crops that you assigned the base class `Crop` to
Hopefully this gives an entry point into the power of classes. You can add more functionality into this one and it automatically apply to all the crops you attached it to.
Although BFAT's tutorial is absolutely correct, it is not the only way to do things, moreover, if you ever move from Flash and AS3 to something else, or even try Starling (a framework that allows to build fast and non-laggy mobile applications in Flash/AS3), you'll find that concept not applicable. It is very Flash-y and I applause to it though.
Instead of making each field subclass the abstract (means, it is never instantiated by itself) Crop class, you can make the Crop class take 1 of these 6 fields as an argument on creation (or later). Basically, you tell "I want to make crop field with wheat graphics". So, let me redo that class a bit.
package
{
// Imports.
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.Event;
import flash.events.TimerEvent;
public class Crop extends Sprite
{
// I agree with the use of Timer.
private var timer:Timer;
// Visuals go here.
private var field:MovieClip;
// Class constructor.
public function Crop(FieldClass:Class)
{
// With "new" keyword you can omit ()
// if there are no mandatory arguments.
field = new FieldClass;
field.stop();
addChild(field);
}
// A function that starts the timer ticking.
public function startGrowing():void
{
timer = new Timer(5000, 4);
timer.addEventListener(TimerEvent.TIMER, grow);
timer.start();
}
// This function is called every timer tick.
private function grow(e:Event):void
{
// Command the graphics to go to the next frame.
field.nextFrame();
}
}
}
Then, the usage. When you create fields, you need to set AS3 classes to them to have access, leaving base class as is, Flash will automatically set it to non-specific MovieClip. Lessay, you have crops.Wheat field and crops.Barley field.
import Crop;
import crops.Wheat;
import crops.Barley;
var W:Crop = new Crop(Wheat);
var B:Crop = new Crop(Barley);
addChild(W);
addChild(B);
B.x = 100;
W.startGrowing();
B.startGrowing();
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
I'm passing some parameters everytime i click a movieclip, and I'm not realising how to remove it
my_mc.addEventListener(MouseEvent.CLICK, someFunct(1,1));
I thought this could work, but it isn't working...
my_mc.removeEventListener(MouseEvent.CLICK, someFunct)
Try stopImmidiatePropagation(); It will stop all evnts
Hope it will help
I don't think that the syntax you posted is actually working, unless someFunct itself returns a function that is the actual event listener (the exception is that Flex has some stuff under the hood that will create the illusion that you can do this). In any case, what you have is more or less an anonymous function if this is remotely working as posted.
The only place you can remove an anonymous function is inside the listener. However, the listener would have to have a more conventional event listener signature (have a single parameter that is the event). Assuming that somewhere in your code there's somebody that looks like that:
protected function someFunct(param1:int, param2:int):void {
return function(e:MouseEvent):void {
e.target.removeEventListener(e.type, arguments.callee);
trace('in listener', param1, param2);
}
}
If you're using Flex, I don't think there's a way to get at where the anonymous function is created to allow the listener to be removed. For more on how this stuff works, try reading this.
I did some testing and figured out how to accomplish this. Below is a test .as main file, just make it the main document class of a new .fla file and run it. You can clearly see it working. As for your exaple, you can just replace this.stage with your movieclip.
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip {
public function Main() {
graphics.beginFill(0x000000, 1);
this.stage.addEventListener(MouseEvent.CLICK, someFunct(1, 1));
}
private function someFunct(p1:int, p2:int):Function {
return someFunct2
}
private function someFunct2(event:MouseEvent):void {
graphics.drawCircle(this.stage.mouseX, this.stage.mouseY, 50);
this.stage.removeEventListener(MouseEvent.CLICK, someFunct2)
}
}
}
If this has not answered your question, please comment back, or edit your question and clarify what you really want. Thank You
UPDATE: OK I am about ready to give up on Pacakages and classes. No answers coming. Not sure what to do. I tried to make the question easier and made a new post but I was down voted for it. as3 calling a function in another class
I am TOTALLY NEW to using PACKAGES and CLASSES. I am finally converting over from the timeline after having so many issues. Please be patient with my lack of knowledge. I need to know how to call a function in the child swf file I loaded from code in the maintime in the parent swf.
There are 2 swf files. Main.swf and pConent.swf
1. Main.swf has code in the timeline of the first frame.
2. pConent.swf is loading a PACKAGE CLASS as file.
QUESTIONS
I am trying to call a function in it from its parent Main.swf. How do I do this?
Here is sections of the code from both. Thanks
Main.swf CODE /// is an AIR for Andrid swf
function LoadContent()
{
TheContent.load(new URLRequest( "pContent.swf"));
TheContent.contentLoaderInfo.addEventListener(Event.COMPLETE, LoadContentTWO);
function LoadContentTWO(e:Event)
{
Content = TheContent.content as MovieClip;
pContent = Content as Object;
addChild(TheContent);
var OSS:String = "device";
trace(pContent); //// comes out as: [object pContent]
pContent.GetOnlineStatus(OSS); ///// HOW DO I GET THIS TO CALL FUNCTION
}
}
A SECTION OF THE "CLASS" in pContent.swf I am trying to call
public function GetOnlineStatus(OS:String)
{
if(OS=="online")
trace("inside ONLINE" );
}
if(OS=="device")
{
trace("inside DEVICE" );
}
}
THE ERROR I AM GETTING
TypeError: Error #1006: GetOnlineStatus is not a function.
UPDATE: I decided to post the FULL PACKAGE ( my first) to see if I am doing it right.
package
{
import flash.display.MovieClip;
import fl.transitions.Tween;
import fl.transitions.easing.*;
import fl.transitions.TweenEvent;
import flash.display.*;
import flash.media.Sound;
import flash.system.*;
import flash.media.SoundChannel;
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class pContent extends MovieClip
{
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
var ScreenY = flash.system.Capabilities.screenResolutionY;
var ScreenX = flash.system.Capabilities.screenResolutionX;
var swf:String;
var daSounds:String;
var images:String;
var videos:String;
var OnlineStatus:Boolean;
//++++++++++++++++++++++++
//++++++++++++++++++++++++
public function pContent()
{
BG.addEventListener(MouseEvent.CLICK, mouseHandlerdown);
}
//++++++++++++++++++++++++
//++++++++++++++++++++++++
//-------- * FUNCTIONS * --------
//-------------------------------
public function mouseHandlerdown(event:MouseEvent):void
{
alpha = .3; // testing
}
public function GetOnlineStatus(OS:String)
{
if(OS=="online")
{
OnlineStatus = true;
Security.allowDomain("*");
trace("inside THE PATH " + ThePath.text);
daSounds = "http://mycontactcorner.com/upload/files/";
swf = "http://mycontactcorner.com/upload/files/";
trace("inside THE DEVICE ONLINE" );
OnlineStatus = false;
swf = "";
daSounds = "content/sounds/";
//LoadMenu();
LoadStage();
LoadBeau();
}
if(OS=="device")
{
trace("inside THE DEVICE ONLINE" );
}
}
//------ * END FUNCTIONS * -----
//------------------------------
}// END FUNCTION pContent
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}//// END PACKAGE
Don't be disappointed, but I won't have a "real" answer to your question, and I am really not going to work through all of your code to solve it, either. It is your own task to learn how to do this, and unless people here are very, very hungry for reputation, no one will do it for you - we will only help you to find the right way.
Your problem is not "packages and classes", so please do not give up on them. They will help you a great deal, once you've started to understand them. Your problem is, that you are not facing a single problem, but actually at least two (and quite substantial ones, I might add):
You need to go back to learn about the basics of object oriented programming in ActionScript. You won't have much luck getting answers to questions like this, otherwise. And believe me, I don't mean that in a patronizing way - it is simply a complicated matter, and it is hard to communicate complicated issues, both when you don't know the terms to express them, or when your counterpart doesn't understand them. Think of it like a high school math problem: You won't ever find a solution to your trigonometry question (or get a decent answer), unless you learn some basic algebra first.
You also have a problem related to loading, application domains, and the Flash Player security model - which are all far more complicated than what you should aim at when trying out OOP stuff. This can be a major obstacle, and unless you want to frustrate yourself, you should try to avoid it, until your program actually runs.
So this here is my advice: Always try to solve one problem at a time. Do not work yourself into such complex scenarios as the one you are in right now, but take step by step, until you've reached a level where you are confident with what you are doing.
Your first issue should be to understand what's going on with classes and objects. Everything else will come later. You should try to isolate your problem in the pContent.swf and get that to work first - or better yet, put everything you need for your program into a single file. Convert to using classes. Then, once you know how to work with those, start learning about more advanced OO, decoupling your code using interfaces, type casting and loading binaries at runtime.
//makes contact with classs but comes out as: [object pContent]
its because you said
pContent = Content as Object;
I am not sure why you are doing this extra step
Change it to this
Content = TheContent.content as MovieClip;
// pContent = Content as Object; //NO NEED OF THIS
addChild(Content); // just in case this gives error change it as addChild(Content as Object);
var OSS:String = "device";
trace(Content); //now see the difference
Content.GetOnlineStatus(OSS); // it calls now
Also, give the link where you posted that scary question :P if it has rest of the code
Sorry if this does not sound like an answer, but I'm going to write a couple of doubts that I have reading your code that can possibly lead to the solution:
Why are you casting it to MovieClip? If you cast it as MovieClip, the compiler it is going to tell you that the method "GetOnlineStatus" doesn't exist, because MovieClip class doesn't have it! I think you have to cast it as pContent
Why are you trying to casting TheContent.content? What is "content"? I had a look to your previous post and I cannot see anything called "content"?
If I ignore my second doubt (TheContent.content issue), I would change the code like this:
Content = TheContent.content as pContent; // your class it's called pContent
addChild(Content);
Content.GetOnlineStatus(OSS); // it calls now
Also, keep in mind that generally it's a good pratice to capitalize name of classes and not variables.
Let me know!
private function GetOnlineStatus
Try making this a public function instead. When it's private it can't be accessed outside the scope of the class that owns it.
I believe that in order to make this work, content property of the Loader. You have to create a reference to the loaded SWF as the class you are trying to call. This class has to be included in the main SWF's project. Then you can call the functions of that particular class in the child.
function LoadContent()
{
TheContent.load(new URLRequest( "pContent.swf"));
TheContent.contentLoaderInfo.addEventListener(Event.COMPLETE, LoadContentTWO);
}
function LoadContentTWO(e:Event)
{
var pContent:GetOnlineStatus = GetOnlineStatus(e.target.content);
addChild(e.target.content); //Assuming that "TheContent was
// declared as var TheContent:Loader , you'd be adding the loader to the stage when I think you actually wanted // to add the content.
var OSS:String = "device";
trace(pContent); //// comes out as: [object pContent]
pContent.GetOnlineStatus(OSS); ///// HOW DO I GET THIS TO CALL FUNCTION
// This should work now. If not, try to loading a function that is not the class' main function. Because I think you might get an "unable to call static function error". I'm a begginner too though, so sorry if I'm wrong. Example: pContent.GetOnlineStatusFunction(OSS);
}
This answer assumes that the pContent.swf contains a class file that looks like this:
package {
public class GetOnlineStatus {
public function GetOnlineStatus (OSS:String) {
//Do your GetOnlineStatus Logic. This is the main function.
}
/*public function GetOnlineStatusFunction (OSS:String) {
//Example non-main function
} */
}
}
Source: http://www.scottgmorgan.com/accessing-document-class-of-externally-loaded-swf-with-as3/
I'm new to ActionScript 3.0 and I am trying to work my way around Object Orientated Programming.
I've designed an application where there are 3 buttons on the stage and a logo. What I want to happen is when a button is clicked, the logo will fade out. Now I understand I need to manipulate the alpha properties of the logo but not sure how I would run the code once the button is clicked. I have my Main.as file loading the properties of the application. So once the FLA file runs, Main.as sets up the buttons and the logo. Now the buttons are put into a display holder and run from menuHolder.as which in turn gets the design of the buttons from button.as - so far with me?
To keep my code clean I have seperated my code into their own files (the design of the buttons into its own .as file, the arrangement of the menu buttons into its own .as file, the logo creation into its own .as file) so that the Main.as file just acts as a loader for placing everything into location on the stage.
So my question is that I want to create an animation for the logo (a fade out animation) where the code would be stored in say animationFade.as for example. Then when a button is clicked, the animation plays and the corresponding page is navigated to.
Here is my code for the setup of the menuBottons.as:
package
{
import flash.display.Sprite;
import flash.text.TextField;
import flash.events.MouseEvent;
import flash.text.TextFormat;
public class menuButtons extends Sprite
{
private var aboutMeBtn:button;
private var galleryBtn:button;
private var contactMeBtn:button;
public function menuButtons()
{
aboutMeBtn = new button();
aboutMeBtn.y = 0;
aboutMeBtn.label = "About Me";
addChild(aboutMeBtn);
aboutMeBtn.addEventListener(MouseEvent.CLICK, onButtonClick);
galleryBtn = new button();
galleryBtn.y = 75;
galleryBtn.label = "Gallery";
addChild(galleryBtn);
galleryBtn.addEventListener(MouseEvent.CLICK, onButtonClick);
contactMeBtn = new button();
contactMeBtn.y = 150;
contactMeBtn.label = "Contact Me";
addChild(contactMeBtn);
contactMeBtn.addEventListener(MouseEvent.CLICK, onButtonClick);
}
public function onButtonClick(event:MouseEvent):void
{
//code to initiate the animationFade.as file
}
}
}
it's this //code to initiate the animationFade.as file that i cannot grasp. It may be something very simple but my head seems to be spinning!
Hopefully I have provided enough information. Like I say I am just learning at the minute and trying to build up slowly.
Thank you
The best way to do this would be to dispatch an event from your button click function. Then, create a listener in your Main.as file that handles the event and tells the logo to fade out.
Maybe something like:
From menuButtons.as
public function onButtonClick(event:MouseEvent):void
{
dispatchEvent(new Event("hide_logo", true));
}
You can read up on the Event Class documentation to learn more about the parameters.
From Main.as (after you create your menuButtons instance)
menuButtonsInstance.addEventListener("hide_logo", hideLogoHandler);
function hideLogoHandler(e:Event):void {
// Fade out logo
TweenLite.to(logo, 1, {alpha:0}); // requires TweenLite
}
This example requires TweenLite from Greensock.
On a side note, for best practice your class names should start with an uppercase character. So "menuButtons" class would be "MenuButtons". Then, instance names would start with a lowercase character. Makes it easier to read if you do something like:
var menuButtons:MenuButtons = new MenuButtons();