Actionscript 3.0: Addition of Document Class causes errors - actionscript-3

I'm trying to learn Actionscript 3.0 with a game I'm making in Flash CS6, and I'm having some issues with the Document Class. Initially, I had a working menu with some scripting for keyboard events and sound. I realized that I needed to store some variables in a way that I could access them from any frame, so I created a Document Class with an empty class and set my game to reference it, and now my menu scripting is generating a compiler error. The error I'm getting is "1046: Type was not found or was not a compile-time constant: KeyboardEvent," which doesn't make any sense to me since it worked just fine beforehand. Anybody have any idea what the problem might be? Thanks!
Document Class:
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
}
}
Menu Script:
import flash.utils.getDefinitionByName;
import flash.ui.Keyboard;
stop();//Used to stay on the current frame
var selection:int = 0;//Will be used to determine which button has its "On" animation activated
var canMove:Boolean = true;
var menuSong:Sound = new MenuSong();
menuSong.play (0 , 9999);//Plays and loops(9999 times) menu theme
var menuMove:Sound = new MenuMove();
var menuSelect:Sound = new MenuSelect();
stage.addEventListener(KeyboardEvent.KEY_DOWN, move);//Calls move function when a key is pressed
function move(event:KeyboardEvent):void{//The line causing the error
if(canMove){
if(event.keyCode == 40){
selection = (selection + 1)%3;//Occurs when down key is pressed
menuMove.play();
}
else if(event.keyCode == 38){
selection = (selection + 2)%3;//Occurs when up key is pressed
menuMove.play();
}
else if(event.keyCode == 32){
canMove = false;
SoundMixer.stopAll();
menuSelect.play();
fadeOut.gotoAndPlay(1);
}
switch(selection){
case 0:
this.singlePlayer.gotoAndPlay("On");
this.multiplayer.gotoAndStop("Off");
this.credits.gotoAndStop("Off");
break;
case 1:
this.singlePlayer.gotoAndStop("Off");
this.multiplayer.gotoAndPlay("On");
this.credits.gotoAndStop("Off");
break;
case 2:
this.singlePlayer.gotoAndStop("Off");
this.multiplayer.gotoAndStop("Off");
this.credits.gotoAndPlay("On");
break;
}//All this just tells the selected button (Based on the selection variable)
//to play its "On" animation, and the other buttons to play their "Off" animation.
}
}

You need to import flash.events.KeyboardEvent as you use it in your code (Menu script).
Why dont you use the script you called "Menu Script" as Document Class ? If the goal of your SWF is what is designed in the Menu Script code, it should be the Document Class.
In a way or another, if you use stage.addEventListener(KeyboardEvent.KEY_DOWN, move); in your code, you must import flash.utils.KeyboardEvent. Same thing for Sound ( import flash.media.Sound) & SoundMixer (import flash.media.SoundMixer).

Related

as3 how to perfom different actions if button is clicked or not

I am a complete n00b.
I'm working on a game. Basically, I have to perform no action if a button is pressed on a certain keyframe, but if it's not clicked, I need the scene to proceed until a certain point and then go to another frame.
In my stupid head I thought: if I can create an empty global variable I could input "something" when the button is clicked on my frame and check on a latter frame "if globalvar == "something": nothing happens, else: gotoAndPlay(where I need)"
Explanatory image:
Apparently that's not how AS3 works. So what can I do?
import flash.events.MouseEvent;
var pressed = "no";
function work(event:MouseEvent):void
{
pedal.visible = false;
cursor_mc.visible = false;
pressed = "yes"
}
pedal.addEventListener(MouseEvent.CLICK, work);
This is what I've got when the action needs to be performed.
Then I would put (I've never written an if statement in as3)
if (pressed == "no") {
gotoAndPlay(some other frame);
}
This would be put on a complete different frame AND LAYER from the previous so that the part in between is still played.
You got to add a new event, and ENTER_FRAME event to which will fire a function on every frame. There you could check whether the button is pressed. For example:
stage.addEventListener(Event.ENTER_FRAME, updateFunction);
function updateFunction(e:Event){
if(pressed == "no"){
if(currentFrame == frame number when you want to check){
gotoAndPlay(some other frame);
}
}
}

Making multiple objects draggable

I have about 50 symbols that I want to make draggable. Nothing fancy, just the ability to click it and drag it to a different location.
I found as3 code for doing so but when I paste it into my file it gives me errors:
**Error** Scene=Scene 1, layer=Units, frame=1:Line 9: The class or interface 'MouseEvent' could not be loaded.
function mouseDownHandler(evt:MouseEvent):void {
That code is:
// Register mouse event functions
fighter_uk.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
fighter_uk.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
// Define a mouse down handler (user is dragging)
function mouseDownHandler(evt:MouseEvent):void {
var object = evt.target;
// we should limit dragging to the area inside the canvas
object.startDrag();
}
function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
}
I'm using flash pro 8, so I tried finding as2 code but couldn't find it.
Also, is there an 'easy' way to code all 50 objects?
I think you're trying to compile AS3 code with AS2 compiler. Try changing your compilation settings to target AS3.
Also you may need to include the class import at the top of your code:
import flash.events.MouseEvent;
To drag 50 objects, add them all on the same container sprite and add the listener to the container sprite only:
var holder:Sprite = new Sprite();
for ( var i:int = 0, l:int = 50; i < l; i++ ) {
var dragee:YOUR_CUSTOM_OBJECT = new YOUR_CUSTOM_OBJECT();
holder.addChild(dragee);
}
addChild(holder);
holder.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
holder.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
holder.addEventListener(Event.MOUSE_LEAVE, mouseUpHandler);
var currentDragee:YOUR_CUSTOM_OBJECT = null;
function mouseDownHandler(evt:MouseEvent):void {
currentDragee = evt.target as YOUR_CUSTOM_OBJECT;
if ( currentDragee !== null ) {
currentDragee.startDrag();
holder.addChild(currentDragee); // bring current to front position
}
}
function mouseUpHandler(evt:Event):void {
if ( currentDragee !== null ) currentDragee.stopDrag();
currentDragee = null;
}
YOUR_CUSTOM_OBJECT being the object class you need to drag. Hope it helps!
This page seems to have the answers you are looking for (AS2 drag and drop). If you've already seen it, you'll need to explain why it's not good enough for your needs.
If you want to drag/drop multiple instances in AS2, you can still add the code to the movieClip symbol, export it from the library and load the instances up using attachMovie (all 50 of them). If they are all different, then attach the code as necessary to the clips themselves, or to some function elsewhere that will capture all the clicks and decide what was clicked. This is all very doable in AS2.
Remember you can use your onClipEvent(load) function to set up a lot of the initial lifting.
Here's a sample I made in AS2 for making a node tree. It's all draggable (mouse drag) and zoomable (with mouse Wheel). You can add nodes by clicking on the little down arrow in the node box. Each node is listening for the mouse.
You'll want to look at this section for the most part:
// Enable drag on button press
on (press)
{
startDrag(this);
}
// Stop the drag on release of mouse button
on (release)
{
stopDrag();
}
Besides this, I'm not really sure how your setup looks, so I hope this helps get the ball rolling. (Check the link, there's lots of little gems in there).
Flash Professional 8 only supports ActionScript 2 & 1
You can follow this official URL and learn how to do that in ActionScript 2, but I extremely recommend you to work with ActionScript 3.

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.

Why is my button instance forgetting its textfield text and event listener?

I'm working on an assignment due at midnight tomorrow and I'm about to rip my hair out. I am fairly new to ActionScript and Flash Builder so this might be an easy problem to solve. I think I know what it is but I do not know for sure...
I'm developing a weather application. I designed the GUI in Flash CS5. The interface has 2 frames. The first frame is the menu which has a zipcode input and a button instance called "submit". On the second frame, it has another button instance called "change" which takes you back to the first frame, menu.
In Flash Builder 4, I wrote a class to extend that GUI called Application. When Main.as instantiates it, the constructor function runs. However, this was my first problem.
public class Application extends InputBase {
public function Application() {
super();
// Y U NO WORK???
this.gotoAndStop(1);
this.change.tfLabel.text = "Change";
}
}
When I ran debug it tossed a #1009 error saying it could not access the property or method of undefined object. It is defined on frame 2 in Flash CS5. I think this is the problem... Isn't ActionScript a frame based programming language? Like, you cannot access code from frame 2 on frame 1? But, I'm confused by this because I'm not coding on the timeline?
Anyway, I thought of a solution. It kinda works but its ugly.
public class Application extends InputBase {
public function Application() {
super();
// Y U NO WORK???
this.gotoAndStop(1); // when app is first ran, it will stop on the first frame which is the menu frame
setButton(this.submit, "Submit", 1);
setInput(this.tfZipCode);
}
private function submitZip(e:MouseEvent):void {
this.nextFrame();
setButton(this.change, "Change", 2);
}
private function menu(e:MouseEvent):void {
this.prevFrame();
setButton(this.submit, "Submit", 1); // if I comment this out, the submit button will return to the default text label and it forgets it event.
}
private function setButton(button:ButtonBase, string:String="", action:uint=0):void {
button.buttonMode = true;
button.mouseChildren = false;
button.tfLabel.selectable = false;
button.tfLabel.text = string;
switch (action) {
case 1:
button.addEventListener(MouseEvent.CLICK, submitZip);
break;
case 2:
button.addEventListener(MouseEvent.CLICK, menu);
break;
default:
trace("Action code was invalid or not specified.");
}
}
}
Its not my cup of tea to run the set button function every time one of the button instances are clicked. Is this caused by frames or something else I maybe looking over?
I believe you have two keyframes & both have an instance of the button component called button.
If you are working on the timeline try putting the button in a separate layer, with only one key frame.
Something like the following:
Ensures that you are referencing the same button every time & not spawning new ones on each frame.

Flash CS6 Error #1009 - Button disappears

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.