ASC3 extending a custom class with MovieClip - gotoAndStop not working - actionscript-3

I'm trying to setup a class that handles screen navigation for a game; called MenuNavigation. I have extended this class with MovieClip so I should be able to access gotoAndStop functions, but I keep getting the error -
"1180 - Access of undefined method gotoAndStop"
. I have also tried:
MovieClip(root).gotoAndStop(frameLabel)
MovieClip(root).gotoAndStop(frameLabel)
Stage.gotoAndStop(frameLabel)"
these do not work either. I have made a few other classes that have extended MovieClip would be this be an issue? is there a limit? Its weird I have done other flash projects and done the exact same thing and never had an issue. I'm sure its something stupid on by behalf. Thanks
Here is the code:
package
{
import flash.display.*;
import flash.events.*;
public class MenuNavigation extends MovieClip
{
public function MenuNavigation()
{
// constructor code
}
// function deals with button navigation handling between frames
public static function loadScreen(evt:MouseEvent)
{
switch(evt.target.name)
{
case "playButton":
gotoAndStop("aboutGame");
break;
case "creditsButton":
gotoAndStop("credits");
break;
case "aboutNextButton":
gotoAndStop("instructions");
break;
case "aboutBackButton":
gotoAndStop("mainMenu");
break;
case "instructionsBackButton":
gotoAndStop("aboutGame");
break;
case "instructionsPlayButton":
gotoAndStop("game");
break;
case "creditsBackButton":
gotoAndStop("mainMenu");
break;
}
}
}
}

public function loadScreen(evt:MouseEvent)
{
....
}
Your main problem is with the scopes. The function loadScreen shouldn't be static. If its static the scope of the function is different and won't have the MovieClip object props and functions.

Related

AS3: class not functioning properly

Sorry for a blurry title, but this is probably the best way I can describe the issue that seems absurd to me by now.
I need a simple action done by an MC: going to a certain frame. I couldn't get it to work, although I had an exact same type of action done by another Movie Clip in the same class code. Here's how I did it:
if (currentItem.type == "blue") {
guy.gotoAndPlay("blue")
}
Yes, the class I'm referring to ('guy') is extended as a Movie Clip. Again, exact same code works fine with other Clips. I tried another method: switching the frame from the Clip's class, the frame it switches to is defined by a variable which is changed by main class. But somehow, this doesn't work either. It gives me the 1069 error. Here's the code of the 'guy' class:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class guy extends MovieClip
{
public static var gotoer:String = "fffuuu"
public function shaman_armsUp()
{
super();
addEventListener(Event.ADDED_TO_STAGE, init)
}
public function init(e:Event):void {
removeEventListener(Event.ADDED_TO_STAGE, init)
armLoop()
}
public function armLoop():void {
if (gotoer == "brown") {
this.gotoAndPlay("brown")
}
if (gotoer == "red") {
trace(gotoer)
this.gotoAndPlay("red")
}
}
}
}
Is there anyone who has a logical explanation for this? Can this be caused by a bug?
maybe the code you are writing in the method shaman_armsUp() should be moved to the constructor?
Follow my edited version of your class guy (also, renamed to Guy, follow the class name convention)
package
{
import flash.display.FrameLabel;
import flash.display.MovieClip;
import flash.events.Event;
// renaming the class name (guy to Guy)
public class Guy extends MovieClip
{
// not sure if using an static variable for this case is the best idea, but I decided to keep because I don't know your initial idea
public static var gotoer:String = "fffuuu";
public function Guy()
{
// move the addedToStage event to the constructor
super();
addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
}
public function shaman_armsUp()
{
}
public function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
armLoop();
}
public function armLoop():void
{
// Note: the value of gotoer is "fffuuu" and there is no conditional for it.
// are you chaging this value before calling armLoop? because when the init method is called it has the same value
// why not try something like:
// checking if the frame exist and if so, calling the gotoAndPlay method (try to imagine if you have 100 frame names? the old approach will be very hard to maintain
if (hasFrameLabel(gotoer))
{
this.gotoAndPlay(gotoer);
}
else
{
trace('frame: ', gotoer, ' not found');
}
/*
if (gotoer == "brown")
{
this.gotoAndPlay("brown");
}
if (gotoer == "red")
{
trace(gotoer);
this.gotoAndPlay("red");
}
*/
}
// helper function to avoid calling a frame that doesn't exist
private function hasFrameLabel(frameLabel:String):Boolean
{
var returnValue:Boolean;
const obj:Object = this.currentLabels;
for each (var i:FrameLabel in obj)
{
if (i.name == frameLabel)
{
returnValue = true;
break;
}
}
return returnValue;
}
}
}

Access of undefined property issues in AS3

I am having a bit of trouble with some AS3. First time using this language and have more experience with web development then OOP so am getting a bit confused.
I am trying to make it so that when someone clicks a 'powerbutton' which is a "movieclip" symbol within flash then another symbol should then become visible. This is all being done within the Kitchen class.
The code for the main class is which i got from a youtube tutorial video i followed;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
public function DragFood() {
myKitchen = new Kitchen;
originalPosition = new Point (x, y);
buttonMode = true;
addEventListener (MouseEvent.MOUSE_DOWN, down);
}
protected function down (event:MouseEvent):void
{
parent.addChild(this);
startDrag();
stage.addEventListener (MouseEvent.MOUSE_UP, stageUp);
}
protected function stageUp (event:MouseEvent):void
{
stage.removeEventListener (MouseEvent.MOUSE_UP, stageUp);
stopDrag();
if (dropTarget)
{
if(dropTarget.parent.name == "bowl")
{
trace("The " + this.name + " is in the bowl");
this.visible = false;
} else {
returnToOriginalPosition();
}
} else {
returnToOriginalPosition();
}
}
protected function returnToOriginalPosition():void
{
x = originalPosition.x;
y = originalPosition.y;
}
}
}
Within it i call the other class;
import Kitchen
public class DragFood extends MovieClip
{
protected var originalPosition:Point;
var myKitchen:Kitchen
The code for the kitchen class is;
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class Kitchen extends MovieClip
{
// This is a function. This particular function has the same name as our class and therefore will be executed first
public function Kitchen()
{
// This is a "call" to another function that is defined later in the program.
init();
trace("Hello world");
}
public function init():void
{
// If we want an object (on the screen or otherwise) to be notified about an event we must add a listener for that event to that object.
// We also need to specify what happens everytime the event we are listening for happens.
PowerButton.addEventListener(MouseEvent.CLICK, handleButtonClicks);
}
//This function is called when the oven on button recieves a click.
public function handleButtonClicks(event:MouseEvent):void
{
OvenOn.visible = true;
trace("the oven is being switched on");
}
}
}
The issue i keep getting is that OvenOn and PowerButton are giving me a undefined access issue and im not sure how to fix it. I have found posts on similar subjects like - Access of Undefined property? Actionscript 3
but im not quite sure how to apply it to my issue if anyone could offer any help that would be great.
When you're programming on the timeline, code is referencing the local namespace, and objects you make there (movieclips, textfields, etc.) are automatically instantiated in that namespace so that you can simply call OvenOn.visible = true. However, for each class, their local namespace is whatever is inside the class, so unless you actually created a property on your class called OvenOn, it will most definitely give you Access of Undefined Property errors.
Think of each class as its own island. For them to touch eachother, they need some sort of connection. That connection can be made once the parent instantiates the class in its own namespace. For example...
var foo:String = "Hello!";
var bar:MyClass = new MyClass();
// At this point, whatever code runs inside of MyClass has no concept of foo, or how to access it.
addChild(bar);
// Now that we've added it to the stage, the bar has some properties that have automatically been populated such as "root", "parent", or "stage".
foo.someProperty = "World";
// Since this namespace has a variable pointing to the instance, we can change properties on that class.
Now that we've instantiated MyClass on the stage, we can reference parent properties the class didn't know about. Mind you, this is not necessarily best practice.
package
public class MyClass extends MovieClip {
var someProperty:String = "cheese";
public function MyClass() {
trace(parent.foo) // this will fail
addEventListener(Event.ADDED_TO_STAGE, test);
}
public function test(e:Event):void {
trace(this["parent"].foo); // this will succeed
}
}
}
If you absolutely must change something that is not part of your Kitchen class, pass either the parent of OvenOn or that object specifically as a property of Kitchen. You could do this a couple ways.
with the Constructor...
var something:*;
public function MyClass(someObject:*) {
something = someObject;
}
public function test():void {
something.visible = false;
}
...or by Assigning the Property...
var bar:MyClass = new MyClass();
bar.something = OvenOn;
bar.test(); // will turn off the OvenOn now that 'something' is pointing to it.

ActionScript 3 - Stage object is null for first operation

I have basically been trying to create a chess game, and it has some basic functionality. I have encountered some runtime errors that I can't seem to fix. I've tried searching around for solutions, and I have found several, but none of them seem to work for me.
I then created a new flash project to see if the error still occurs, just to make sure that it's not another part of my program that is causing the issue.
The stage has a pentagon object (a MovieClip) on it, which has an instance name of PentaGray and a class of Gray. There is an intermediary class called PentaClass.
The Main (document) class:
import flash.display.MovieClip;
import PentaClass;
import Gray;
public class Main extends MovieClip
{
// public var Natsu:String;
public function Main()
{
FairyTail();
}
public function FairyTail()
{
trace("PentaGray = " + PentaGray);
trace("PentaGray's name is " + PentaGray.name);
PentaGray.TraceThis();
}
}
PentaClass class:
public class PentaClass extends Main
{
public function PentaClass()
{
}
public function TraceThis():void
{
trace("Fairy Tail :D");
}
}
Gray class:
public class Gray extends PentaClass
{
public function Gray()
{
// TraceThis();
}
}
Running the program like this causes this to be printed to the output window:
PentaGray = null
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main/FairyTail()
at Main()
at PentaClass()
at Gray()
at flash.display::Sprite/constructChildren()
at flash.display::Sprite()
at flash.display::MovieClip()
at Main()
PentaGray = null
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Main/FairyTail()
at Main()
If I change the code in the Main class to:
if (PentaGray)
{
trace("PentaGray's name is " + PentaGray.name);
PentaGray.TraceThis();
}
Then this is output:
PentaGray = null
PentaGray = [object Gray]
PentaGray's name is PentaGray
Fairy Tail :D
Also, if I run the function from Gray by uncommenting the statement in its constructor, it works properly, but for my game, I need to run a subclass function from the document class.
What I would like to to know is, why is PentaGray null when the program starts? I thought that the objects that are placed on the stage using the IDE are initialised before any written code runs, but this doesn't seem to be the case.
I've tried using event listeners (ENTER_FRAME and a Timer) but they still didn't solve the issue.
How can I change the program so that the object isn't null when certain code, e.g. the FairyTail() function, is executed? Have I not written my code properly or is this an issue with Flash/ActionScript itself?
By putting the call to FairyTail() in the Main class in the Main function, you have put that in the 'constructor' for the main object. The constructor of the Main object is the very first thing that has to run, because nothing can be created until the main object is created. And when the main object is created, the constructor is called first.
If you want something to run right when PentaGray is created, put it in the constructor of PentaClass:
public class PentaClass extends Main
{
public function PentaClass()
{
Main.FairyTail();
}
}
Or, if you just want it to happen at the start, you can just put it after the class declaration in the main file.
#main document
import flash.display.MovieClip;
import PentaClass;
import Gray;
public class Main extends MovieClip {
//...
}
Main.FairyTail();
By the way, it doesn't make sense to me that the PentaClass extends the Main class. Why don't you just make another class for it to extend?
Off course, your stage is not ready. Use the bootstrap done below in your main class.
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
FairyTail();
}
Cheers

ActionScript get Class type, that is out of package?

Main.as
package{
public class Main extends Sprite{
public function Main () {
new ProxyClass(new HiddenClass())
}
}
}
class HiddenClass(){
...
}
ProxyClass.as
package{
public class ProxyClass extends Sprite{
public function ProxyClass(value:*) {
trace(value, value.constructor) // [object HiddenClass] [class HiddenClass]
switch (value.constructor) {
case Sprite:
...
break;
case "class HiddenClass": //???????
...
break;
}
}
}
}
I have some legacy code and cannot change Main.as. I need to check Class type of value inside my ProxyClass, but HiddenClass is out of package and is visible only for Main.as.
How can I validate HiddenClass ?
Well, considering it is not a visible property and you will not get its definition, you will very probably have to rewrite your switch statement to use Strings instead of Object. Just cast the value.constructor to String and then use it as case "[class HiddenClass]".
Use flash.utils.getQualifiedClassName. It's a global function that'll give you the package + class name. For example:
MyClass // default package
com.mycompany.mypackage::MyClass // package com.mycompany.mypackage
So essentially:
package{
import flash.utils.getQualifiedClassName;
public class ProxyClass extends Sprite{
public function ProxyClass(value:*) {
trace(value, value.constructor) // [object HiddenClass] [class HiddenClass]
var strClass:String = getQualifiedClassName(value);
switch (strClass) {
case "flash.display::Sprite":
...
break;
case "Main.as$9::ProxyClass":
...
break;
}
}
}
}
Confirm each of these Strings are the right ones to be checking for, but when I experimented with a couple of my own classes (including a hidden one), it looked like these are the values you would be getting back.

AS 3.0: Calling a method, which is defined in another class, from Main class gives Error 1120

I have two classes. The Main class calls a function, which is defined in a Second class. I'm getting the following error:
Error 1120: Access of undefined property myFunction
Basically, I am creating buttons in the Main class that will add a corresponding Child to an Object in the Second class (if you click one button, child x1 will be added, if you click another button, child x2 will be added, and so forth).
Here's the relevant code for the Main.as file:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class Main extends MovieClip {
private var x1:X1 = new X1();
private var x2:X2 = new X2();
public function Main():void {
addPlayers();
}
public function addPlayers():void {
addChild(x1);
addChild(x2);
x1.x=325;
x1.y=5;
x2.x=366;
x2.y=5;
x1.label = "dog";
x2.label = "cat";
x1.addEventListener(MouseEvent.CLICK, selectPlayer);
x2.addEventListener(MouseEvent.CLICK, selectPlayer);
}
}
}
The Second.as file code is:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.MouseEvent;
public class Second extends MovieClip
{
public var myVar:MyVar = new MyVar();
public function Second():void
{
addChild(myVar);
}
private var mc_x1:Mc_x1 = new Mc_x1();
private var mc_x2:Mc_x2 = new Mc_x2();
public function selectPlayer(event:MouseEvent):void
{
if (Game(this.parent).turn == 0) {
myVar.addChild(mc_x1);
} else {
switch (event.currentTarget.label) {
case "dog":
myVar.addChild(mc_x1);
break;
case "cat":
myVar.addChild(mc_x2);
break;
default:
myVar.addChild(mc_x1);
}
}
}
}
}
i've tried defining a new variable as a public static var and that hasn't worked. i've also tried to import the Second class in the Main class and that didn't work either. any thoughts?
thank you!
If I'm understanding what your code says, you can't do what your doing. Even though you are listening to events on X1 and X2, you are listening to them FROM main. In other words, main is attempting to handle the event, and it's not finding the function you specified (selectPlayer). If you want all event handling to happen in main, then main will have to call into X1 and X2 when it receives an event.
I agree with ThatSteveGuy , in Main you are calling a function that doesn't exist, namely selectPlayer(). Following your code the first thing you should do is add a selectPlayer() function in Main.
Then you would need to add an instance of the Second class in Main in order for the following to work
private function selectPlayer(event:MouseEvent):void
{
second.selectPlayer(event);
}
Now it's a bit difficult to advise you any further because this way of doing things looks a bit convoluted but then again I would need to see the big picture. This is just an explanation about why your code doesn't work. Also, in the Second class , selectPlayer may throw an error because Game(this.parent ) will return a null value so you won't be able to access the turn property...
Is there a good reason why you need to add the two buttons in Main as opposed to adding them in Second?
try this
public function Second():void
{
this.addEventListener(MouseEvent.CLICK, selectPlayer);
addChild(myVar);
}
(and don't forget to remove x1.addEventListener, x2.addEventListener from main)