I have a parent class called 'main.as'. I am trying to get the child class to call main's function. They both reside in the same folder.
// main.as //
package {
public class main extends MovieClip {
public function main() {
var child:child_mc = new child_mc(this);
}
public function callFunction():void {
trace("Done it");
}
}
}
.
// child.as //
package {
import main;
public class child extends MovieClip {
private var main:MovieClip = new MovieClip();
public function child(main:MovieClip):void {
this.main = main;
main.callFunction();
}
}
}
This is the error I've been getting:
TypeError: Error #1006: callFunction is not a function.
so I tried doing a trace like this
trace(main.callFunction);
and it says undefined. Can someone tell me what I am missing. I get this feeling its a very basic thing that I have overlooked!
Your "child" package is defined as "main". I'm not even sure how it complied, let alone run to the point of showing the error message you got.
I believe the code below should do what you expected.
(I also took the liberty to rename the classes to use CamelCase (with initial caps) to adhere to best practices and to be easier to distinguish from variable names.)
Main.as
package {
public class Main extends MovieClip {
public function Main() {
var child:ChildMC = new ChildMC();
child.main = this;
}
public function callFunction():void {
trace("Done it");
}
}
}
EDIT: I just saw your comment that points out that child_mc is a MovieClip in the Library. I guess then that the child class is set as the Base Class of the child_mc?
If so, you cannot pass properties through the instantiator, you need to find another way to pass along the instance of the Main class to the Child class.
One way would be to add a setter, like the following:
Child.as (Base Class for ChildMC)
package {
public class Child extends MovieClip {
private var _main:Main;
public function Child() {
}
public function set main(main:Main):void {
this._main = main;
this._main.callFunction();
}
}
}
Related
I have trouble with actionScript , im trying to use a simple one line code to access a method inside the Document Class (Main) , but every time i got error . i tried the same code with a movieClip on stage, it work nicely .
Main Class linked to the fla :
package {
import flash.display.*;
import flash.events.*;
public class Main extends MovieClip {
public function Main() {
if (stage) {
init();
}
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
button.addEventListener(MouseEvent.CLICK,_click);
}
private function _click(e:MouseEvent):void {
var l:Leecher = new Leecher();
l.leech();
}
public function callMe():void {
trace("hey nice work");
}
}
}
Leecher Class :
package {
import flash.display.*;
public class Leecher extends MovieClip {
public function leech():void
{
trace(" leech function ");
Main(parent).callMe(); // output null object
Main(root).callMe(); // output null object
Main(Main).callMe(); // output null object
}
}
}
The Same code , but the class linked to a button on stage
package
{
import flash.display.*;
import flash.events.*;
public class Button extends MovieClip {
public function Button() {
this.addEventListener(MouseEvent.CLICK,r_click);
}
private function r_click(e:MouseEvent):void {
var l:Leecher = new Leecher();
l.leech();
Main(parent).callMe(); // hey nice work
Main(root).callMe(); // hey nice work
Main(Main).callMe(); // output null object
}
}
}
The errors are because when that code runs, the Leecher instance has not yet been added to the display list, and as such does not have a parent or root or stage (so parent is null).
Here is a breakdown of what's happening (explained with code comments):
private function _click(e:MouseEvent):void {
//you instantiate a new Leecher object
var l:Leecher = new Leecher();
//you call leech, but this new object does not have a parent because you haven't added it to the display list (via `addChild(l)`)
l.leech();
}
//your saying parent should be of type Main, then call the callMe method. However, parent is null because this object is not on the display list
Main(parent).callMe();
//same as above, except using root
Main(root).callMe();
//Here you are saying the Main class is of type Main (which since Main is a class and not an instance of Main will error or be null)
Main(Main).callMe();
The root, parent & stage vars of a display object are only populated when said display object is added to to the display list. In the case of root & stage the parent (and any grand parents) must also be added so that the top most parent/grandparent is the stage.
As a result, you need to wait until it's safe to access parent by listening for the Event.ADDED_TO_STAGE event.
private function _click(e:MouseEvent):void {
var l:Leecher = new Leecher();
//call the leech method once the child has been added to the stage and has a parent value
l.addEventListener(Event.ADDED_TO_STAGE, l.leech, false, 0, true);
addChild(l);
}
If you do the above, you'll need to add an optional event parameter to the leech method or you'll get an error:
public function leech(e:Event = null):void
{
To make your Main class easily accessible, you could use a static reference.
Static vars are not tied to an instance of an object, but to the class itself.
public class Main extends MovieClip {
//create a static var that holds a reference to the root/main instance
public static var main:Main;
public function Main() {
//assign the static var to this (the instance of Main)
main = this;
//...rest of code
If you do that, you can asses your root anywhere in your code by doing Main.main so in your example you could then do:
Main.main.callMe();
I'd recommend reading about static vars more before going crazy using them. Doing what I've just shown for an easy reference to your document class / root is safe, but in other contexts there are some memory & performance nuances it's best to be aware of.
i'm trying to create a flash game, but i'm having trouble with my classes. i'm importing the classes on the main script. they're imported okay, i've tested it all. but i dont know how to use classes inside another class
this is what i've got so far:
class Class.Player {
public static var self:MovieClip;
public static var bullet:Class.Bullet;
function controls() {
//Shoot
if (Key.isDown(Key.SPACE)) {
bullet = new Bullet(100, 100);
}
}
it loads the class and declares the variable, but it claims "Bullet" is not an existing method. it is an existing method, and it works when i call it from the main script.
also, do i need to declare the class like public static var bullet:Class.Bullet;? it's the only way that works for me but wondered if there's a better way?
It looks like you are having problems with the naming of your classes. You don't have to call your classes Class.Name. Just use Name.
In your case, you could have a file called
Player.as
With this content:
package {
import flash.display.MovieClip;
public class Player extends MovieClip {
public private var bullet:Bullet;
public function Player(){
//constructor
}
function controls() {
//Shoot
if (Key.isDown(Key.SPACE)) {
bullet = new Bullet(100, 100);
}
}
}
}
And then a file called
Bullet.as
With this content:
package {
import flash.display.MovieClip;
public class Bullet extends MovieClip {
public function Bullet(x:Number, y:Number){
//constructor
}
}
}
You can read more information about creating and using custom classes here: http://www.flashandmath.com/bridge/intro/class.html
You're putting your package information in the Class name. I have no idea how this is even compiling for you (especially given that Class is a reserved word.
Your files should look more like:
package somePackage {//somePackage instead of the reserved word Class you were using
import someOtherPackage.Bullet;
public class Player extends MovieClip {
public var bullet:Bullet;
public function Player():void {
super();
//other constructor logic here
}
}
}
Before firing away, I know there are many questions here on SO that are quite similar. Yet, none of the solutions given were of any help to me, probably because my case is a little different.
I have a main class which loads an external class (separate .as file). In this external class, there are several objects which have tweens and time events bound to them.
What I want to do, is starting the animations when a certain function is called in my Main class. However, I've tried numerous things to stop and/or reset the animations in the external class, so it will start from the beginning if the required function in Main is called.
Main.as:
package {
//required imports
public class Main extends MovieClip {
var myClass:MyClass = new MyClass; //this is the external class
var button:Button = new Button; //movieclip in the library
public function Main() {
addChild(myClass); //I want to do this here so the objects show from the start
//try 1: myClass.gotoAndStop(1);
//try 2: myClass.stop();
button.addEventListener(MouseEvent.MOUSE_CLICK, playAnimation);
}
function playAnimation (e:MouseEvent) {
//try 1: myClass.gotoAndPlay(1);
//try 2: myClass.start();
//try 3: controlling the startTweening() function in MyClass, I tried different ways
}
}
}
The problem starts in the Main class above. I don't want to animate yet!
MyClass.as:
package {
//required imports
public class MyClass extends MovieClip {
//vars
public function MyClass() {
startTweening();
}
function startTweening() {
//tween event
//calling next function (with use of a TimerEvent) after tween is done. This is repeated several times.
}
}
}
Everything in this class works fine, so that's not the problem.
If this makes any difference, I used TweenMax in MyClass for tweening. I didn't use the timeline in the .fla.
Any help would greatly appreciated!
If you don't want to animate at creation of MyClass remove startTweening(); call from the constructor of MyClass.
Make startTweening(); a public function and call it whenever your need with myClass.startTweening().
Here the MyClass
public class MyClass extends MovieClip {
//vars
public function MyClass() {
}
public function startTweening() {
//tween event
//calling next function (with use of a TimerEvent) after tween is done. This is repeated several times.
}
}
and here the Main class
public class Main extends MovieClip {
var myClass:MyClass;
var button:Button = new Button; //movieclip in the library
public function Main() {
myClass = addChild(new MyClass()) as MyClass;
button.addEventListener(MouseEvent.MOUSE_CLICK, playAnimation);
}
function playAnimation (e:MouseEvent) {
myClass.startTweening();
}
}
I am a little confused by this concept.
If I override a public function in a base class, I would have thought that this override function is called and the original is ignored? though this doesn't seem to be the case...
public class AbstractScreen extends Sprite
{
public function AbstractScreen()
{
}
public function updateLanguage():void
{
trace("WARNING: need to override public function updateLanguage()");
}
}
public class Start extends AbstractScreen
{
override public function updateLanguage():void
{
title.text = _model.language.start
title.setTextFormat(titleFormat);
}
}
public class ViewManager extends Sprite
{
private var _model:Model;
private var _screens:Array;
public function ViewManager(model:Model)
{
_model = model;
_model.addEventListener(AppEvent.INIT_VIEW, initViews);
_model.addEventListener(AppEvent.UPDATE_VIEW, updateView);
_model.addEventListener(AppEvent.CHANGED_LANGUAGE, changeLanguage);
}
private function initViews(e:AppEvent):void
{
trace("View Manager: initViews");
_screens = new Array(new Start(_model), new TakePhoto(_model));
dispatchEvent(new ViewEvent(ViewEvent.VIEW_READY));
}
private function changeLanguage(e:AppEvent):void
{
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}
}
}
If my model dispatches a CHANGED_LANGUAGE event, the text in the views gets updated, But I also get a trace of "WARNING: need to override public function updateLanguage()" What could I be doing wrong?
You are right, this should not call the base class function. Are you sure there is no call to
super.initLanguage()
within your override?
Most IDE's add this call in the function body automatically, if they create an override for you.
EDIT
From your edit I see your are iterating over two objects of the types Start and TakePhoto. I assume TakePhoto is also derived from AbstractScreen and the trace may be comming from this one.
Also I suggest to use the abstract base class in your iteration.
for each (var screen:AbstractScreen in _screens)
{
screen.updateLanguage();
}
Suppose in document class
public class Test extends MovieClip
{
public function Test()
{
var object1:ClassA = new ClassA();
//addChild(object1);
object1.accessRoot();
}
}
public class A extends MovieClip
{
public function accessRoot()
{
var mc : MovieClip = root as MovieClip;
mc.box.visible = false;
}
}
Now box is placed at stage. but when Class A is added to Test Class, it works and when object of Class A is not added in Test constructor, root becomes in-accessible. Is there any way that objects not on display-list can access root or display-list objects??
I would not recommend having your classes fiddle around with root or stage, it's way better to dispatch events and have the proper encapsulation.
Hacky way:
public class A extends MovieClip
{
private var _root:MovieClip;
public function A(root:MovieClip)
{
_root = root;
}
public function accessRoot()
{
_root.box.visible = false;
}
}
Proper way:
public class A extends MovieClip
{
public static const ACCESS_ROOT:String = "access_root";
public function accessRoot()
{
dispatchEvent(new Event(ACCESS_ROOT));
}
}
// in your document class
var myA:A = new A();
myA.addEventListener(A.ACCESS_ROOT, handleAccessRoot);
public function handleAccessRoot(e:Event):void{
box.visible = false;
}
I normally create a sort of base class that holds a reference to the document class - or "main" class. Anything that I create from here that should need reference to anything defined in Main would extend Element. Example:
The Main class (or document class):
public class Main extends MovieClip
{
/**
* Constructor
*/
public function Main()
{
var obj:MyElement = new MyElement();
obj.main = this;
// stage will be outputted
}
}
Element - which stores reference to the main class.
It also contains an init() function which I generally use in place of a constructor by overriding it.
public class Element extends MovieClip
{
private var _main:Test;
public function set main(m:Main):void
{
_main = m;
init();
}
/**
* Called when _main is defined
*/
protected function init():void
{
// override me
}
public function get main():Main{ return _main; }
}
And here's how you would use Element as a base class for your classes:
public class ClassA extends Element
{
/**
* Override init rather than using a constructor
*/
override protected function init():void
{
trace(main.stage);
}
}
The only thing really to note is that you of course have to set the _main property whenever you create an object. (as shown on line 9 of Main).