AS3 - passing the main timeline/stage into an external class - actionscript-3

Suppose I have the following class
package {
import flash.display.Stage;
public class CustomObject {
private var stage:Stage;
public function CustomObject(stageRef:Stage) {
// stage access through
// constructor argument
stage = stageRef;
}
}
}
Which is not a document class. I wish to pass the stage of the main timeline into the class, say on frame 1
stop();
var c:CustomObject = new CustomObject(this.stage);
Is this the right way of passing the stage of the main timeline into another class?

That will work perfectly well - but if your custom class is extending a display object of any kind (Sprite, MovieClip, etc) it will have it's own stage property which is populated automatically if your object is in the display tree. I believe this would also mean your private variable would result in a compiler error.

Related

creating movie clip instance using class in ActionScript3

First of all I want to say that I've just a couple hours experience with AS3.
Now, I have 2 .as files, one of them is main.as and the second one is Ship_.as
main.as :
package{
import flash .display.*;
// import Enemy;
public class main extends MovieClip{
public function main(){
var hero:Ship_=new Ship_();
addChild(hero); // I have to use addChild here also.
}
}
}
and Ship_.as is :
package{
import flash .display.*;
public class Ship_ extends MovieClip{
private var myHero:Ship=new Ship(); // moved inside of class definition
public function Ship_(){
addChild(myHero); // I think I added my movie clip into stage by this.
}
}
}
and here is my Ship MovieClip : http://prntscr.com/2pjzdwv
When I test it I get an error which says that "1013: The private attribute may be used only on class property definitions."
If I change private var myHero:Ship=new Ship(); to public var myHero:Ship=new Ship(); I get 1180: Call to a possibly undefined method addChild. error. Is there anyone to help me ?
EDIT
To be able to see space movieClip into screen, I have to use two addChild() method as I comment in the code,altough I thought the one inside Ship_ constructor would be enough for that.Could you explain why should I also use addChild(hero); ?
package{
import flash .display.*;
public class Ship_ extends MovieClip{
private var myHero:Ship=new Ship(); // moved inside of class definition
public function Ship_(){
addChild(myHero); // moved inside of contructor
}
}
}
When you call addChild() in Ship_, it adds myHero to the instance of Ship_. But where is Ship_'? At this point, it's just a variable inside of Main.main(), but it hasn't been added or anything.
So what you have is a lot like three boxes, A, B, and C. At first they're all laid out separtely, without one inside of another. But then you put Box C into Box B. But now you just have C inside of B, and A is still off by itself. So to complete the process, you have to put Box B into Box A, and since C is already inside of B, this will make it where C is ultimately inside of A as weel.

How AS3 class files.as work together with FLA file?

I have two questions: Can i write app using just *.as files, and then compile them somehow in SWF? (i am making myself a webpage now)
Secondly, please look at the code, my problem is the same - I can't render text field onto stage, to be visible.
Flash say's 'undefined method addChild.' and 'Access of undefined property tekstuKaste through a reference with static type Class.'
This is a constructor type class inic which kinda serves for initialization, cos all i do is, I make an instance OF THIS class in FLA file by ActionScript, and expect, all application to work.
package {
import pacinas.visuals.*;
import pacinas.visuals.AE_kanva;
public class inic {
public function inic() {
trace("===========");
trace("inicializēt un izsaukt visu no Kanvas klases");
trace("===========");
trace(" ");
var kanvas:AE_kanva = new AE_kanva();
trace(" ");
kanvas.varis();
trace(" ");
trace("===========");
trace("inicializēt un izsaukt visu no Lauki klases");
trace("===========");
trace(" ");
var laukiTxt:BE_tekstaLaukiPrimitive = new BE_tekstaLaukiPrimitive();
trace("");
laukiTxt.simpleText();
addChild(BE_tekstaLaukiPrimitive.tekstuKaste);
}
}
}
There is another EXTERNAL CLASS By whom i hoped to place a rectangles - that does not work too. Example:
package pacinas.visuals
{
import flash.display.Sprite;
public class AE_kanva extends Sprite
{
public function AE_kanva()
{
var kvad:Shape = new Shape();
kvad.graphics.beginFill(0xFF0000);
kvad.graphics.drawRect(0, 0, 100,100);
kvad.graphics.endFill();
addChild(kvad);
trace("konstruktors - zīmē kanvu");
}
public function varis()
{
trace("te glabaas variaabljus");
var ff:int = 4;
var dd:int = 8;
}
}
}
And here is class i hoped will make text box for me (to fill it with XML later)
package pacinas.visuals
{
import flash.text.*;
import flash.display.Sprite;
public class BE_tekstaLaukiPrimitive extends Sprite
{
public var tekstuKaste:TextField = new TextField();
private var kontinents:String = new String ("XML SATURU CMON! a123");
public function BE_tekstaLaukiPrimitive():void
{
trace("teksta rāmis = konstruktora klase");
addChild(tekstuKaste); <--CAN'T GET THIS TO WORK!!!
tekstuKaste.text = kontinents;
}
public function simpleText()
{
trace("nekonstruktora f-cija no Teksta lauki");
}
}}
p.s. I do not use document Class. Ok I will if it's needed. But how?
Can I write app using just *.as files, and then compile them somehow into a SWF?
Yes - using the Flex SDK you can write pure ActionScript and compile it down into a working SWF. FlashDevelop is a good IDE that takes advantage of this.
You will however need to understand how the document class works.
Flash says undefined method addChild. and Access of undefined property tekstuKaste through a reference with static type Class.
In your code, this line is causing your issue:
addChild(BE_tekstaLaukiPrimitive.tekstuKaste);
The first error undefined method addChild is because your class inic does not extend a class that implements the method addChild(). DisplayObjectContainer defines this method, so you'll want to extend that as a minimum, like this:
public class inic extends DisplayObjectContainer
The second error is because you're attempting to access a property of the class BE_tekstaLaukiPrimitive as if it were static. I suspect what you actually wanted to do was this:
addChild(laukiTxt); // laukiTxt is the instance you created.

Get instance objects which are not on first frame

I'm using actionscript 3.0 and Flash Professional CS5.5
I ran into a problem with instance objects which are not on the first frame.
My first frame is a menu and my second frame contains a TLF text field.
I have given the text field an instance name, let's say "username_txt".
Now if I turn off the "Automatically Declare Stage Instances" and do this in my main class
public class MainClass extends MovieClip {
public var username_txt:TLFTextField;
public function MainClass() {
username_txt.text = "anything";
}
}
I will receive a run time error stating that I try to access the property of a null object. (I have import all the necessary classes so that is not the problem)
This does not happen when I put the text right in the first frame though.
Any help?
Thanks in advance
As the text field has not yet been instantiated since the frame has not yet been reached, I'm unsure there is an elegant way to perform this task.
Perhaps a better model would be to decouple your data model from your views.
Create a singleton class to store data:
package
{
public class ApplicationModel
{
/** Singleton instance. */
private static var instance:ApplicationModel = new ApplicationModel();
/** Return singleton instance. */
public static function getInstance():ApplicationModel
{
return instance;
}
/** Data Model */
public var username:String;
/** Constructor as singleton enforcer */
public function ApplicationModel()
{
if (instance)
throw new Error("ApplicationModel is a singleton and can only be accessed through ApplicationModel.getInstance()");
}
}
}
Then from within anywhere such as keyframes or classes, you can get the instance of the object, implemented either as:
ApplicationModel.getInstance().username = "test";
Or a better practice would be:
var applicationModel:ApplicationModel = ApplicationModel.getInstance();
applicationModel.username = "test";
As per your example:
public class MainClass extends MovieClip {
public var username_txt:TLFTextField;
public function MainClass() {
ApplicationModel.getInstance().username = "anything";
}
}
Then, on the frame you need to update your TLFTextField (frame script of frame 2), you set the text based upon the model:
username_txt.text = ApplicationModel.getInstance().username
Your view will always update when needed.

AS3: Access my Main.as from a movieclip on stage

Using Adobe Flash Professional CS6, AS3
Please let me know if I need to provide any more info
I am trying to set up a navigation menu and my question is, "How do I get a MovieClip to call a function in my Main.as file from the Stage?" There is only one frame (I do not want more) and the different menu screens, which are just MovieClips, are added to the stage with AS when needed. I have a public function in the file Main.as called _About(), that my MovieClip, "MenuScreen", cannot access. I can successfully have _Menu() add a MovieClip to the stage with eventListeners, but when the mc makes the call back to change screens I get this error:
TypeError: Error #1034: Type Coercion failed: cannot convert flash.display::Stage#51ca0d1 to flash.display.MovieClip. at MenuScreen/clickAbout()[MenuScreen::frame1:32]
Frame1:32's code is:
MovieClip(parent)._About();
Line 51 in my Main.as is:
public function _About():void
{
trace("The About Function");
}
Below I have detailed more about Main.as with most of the fat trimmed.
package
{
import stuff
public class Main extends MovieClip
{
//Load the screen MCs onto the stage
public var _menu:MenuScreen = new MenuScreen();
public var _about:AboutScreen = new AboutScreen();
public var isMenu:Boolean = true;
public var isAbout:Boolean = false;
public function Main()
{
_Menu();
}
public function _Menu():void
{
isMenu = true;
stage.addChild(_menu);
}
public function _About():void
{
trace("The About Function");
}
An easy solution to your problem would be to add the menu items not to the stage! Instead add them to your main class. This way the parent of your items is instead main.as
But then you need to cast the parent to Main
Main(parent)._About();
Also not very nice. The items should not now what is behind them.
The best way is to do it, is to dispatch events from the different screens.
Means: you create your screen objects an there are dispatching custom events when a screnn change should happen.
dispatchEvent(new Event("showAbout"));
in your main class you handle the events like:
public function Main()
{
_Menu();
_menu = new MenuScreen();
_menu.addEventHandler("showAbout", showAboutHandler);
}
public function showAboutHanlder(e:Event):void
{
_About();
}
Even more better is a custom event with a screen identifier as a param. This way you just add one handler and decide in the handler code which screen to be displayed.
With the event handling in place, your menu items have no direct connection to the main. Also the main needs no further information about the screen classes.
Set static property :
public static var instance:Main;
public function Main(){
instance = this;
_Menu();
}
and then from anywhere You can use code :
Main.instance._About();
It would help to see MenuScreen's complete class, but here's what's probably going on:
You're instantiating at public var _menu:MenuScreen = new MenuScreen(); and when this happens it's probably making the call to MovieClip(parent)._About() before you've added MenuScreen to the stage at stage.addChild(_menu); - It doesn't have a parent yet when this occurs and the error incurs.
Two ways to get around this:
Add a required parameter in MenuScreen's constructor that references your Main class. Your constructor in MenuScreen would start with public function MenuScreen($main:Main){ and when you instantiate MenuScreen from Main class you would write public var _menu:MenuScreen = new MenuScreen(this); now you can use $main._About() in MenuScreen's constuctor.
In MenuScreen's constructor add a listener that checks when it's been added to the stage: addEventListener(Event.ADDED_TO_STAGE, addedStage). In the function addedStage you can properly call for a parent or the stage, and MovieClip(parent)._About() will probably work here.

Reference MovieClip After it is Added to Stage as a Child

I am currently having problems referencing a MovieClip child which I add to the Stage from the Document Class. Basically when the MovieClip child is added to the Stage from the Document Class, I want a certain MovieClip already on the Stage to reference it once it is on the Stage.
Also, if it is possible, I don't want the MovieClip referencing the child being added to the Stage to have parameters linking it with the Document Class, because I plan on nesting this MovieClip within another MovieClip later on in the future.
Here is the code for the MovieClip class which is referencing the child once it is added to the Stage:
package com.gameEngine.assetHolders
{
import com.gameEngine.documentClass.*;
import com.gameEngine.assetHolders.*;
import com.gameEngine.assetHolders.Levels.*;
import flash.display.*;
import flash.events.*;
public class FallingPlatform extends MovieClip
{
public var _document:Document;
// Trying to reference "_player"
public var _player:Player;
public var fallState:Boolean;
public var platformYSpeed:Number = 0;
public var platformGravityPower:Number = 0.75;
public function FallingPlatform()
{
this.addEventListener(Event.ADDED_TO_STAGE, initFallingPlatform);
// constructor code
}
public function initFallingPlatform(event:Event)
{
this.addEventListener(Event.ENTER_FRAME, dynamicFall);
this.addEventListener(Event.ENTER_FRAME, hitTest);
}
public function dynamicFall(event:Event)
{
if (this.fallState)
{
this.platformYSpeed += this.platformGravityPower;
y += this.platformYSpeed;
}
}
// Trying to reference "_player"
public function hitTest(event:Event)
{
if (this.hitTestPoint(_player.x, _player.y + 1, true))
{
this.fallState = true;
}
}
}
}
The player is initialized in the Document class, right? So for me, the best option is either passing the player reference in the constructor of your FallingPlatform class like this
public function FallingPlatform (thePlayer:Player) {
this._player = thePlayer
}
or having a setter method to pass it to it. In this way, you're not tying the structure of your code
public function set player (thePlayer:Player):void {
this._player = thePlayer
}
Hope it helps!
If you set a document class for a fla file every movieclip on the stage can be accessed by it's instance name - just as you wold create a var with its name.
Event more, you can do something like that:
If you place two movieclips on the stagefor example mc1 and mc2 you can add them as variables to the document class.
package{
public class DocClass{
public var mc1:MovieClip;
public var mc2:MovieClip;
[...]
}
}
and than you can access those movieclips from your class with code hints form your IDE (flash or flashbuilder)
the opposite is also availible: define variables in your class and than access them in flash
! it works best when your document class extends a Sprite, I haven;t tested it on extending from a MovieClip but it should also work