I have a movie clip with an external class attached.
here is the MC code (I've shorten it only for the relevant part...)
package {
//all the imports here...
public class mc_masterChapter extends MovieClip {
public function mc_masterChapter() {
trace (picFile,strChapTitle);
}
//Properties
public var picFile:String;
public var strChapTitle:String;
}
}
In the main class file I'm adding this object to stage using addChild:
var masterChapter:mc_masterChapter = new mc_masterChapter;
masterChapter.picFile = "pic_Chap1.jpg";
masterChapter.strChapTitle = "ABCD:
addChildAt(masterChapter,1);
now, the trace in the MC class code gives nulls to both parametes but if i put a trace inside the MC timeline (instead of the attached class code), it gives the right value!
how can I access the values from the MC class itself without getting nuls?
Thank you.
It works! Let me explain:
var masterChapter:mc_masterChapter = new mc_masterChapter; // Calls class constuctor
// so calls trace() too!
// You will get null null
masterChapter.picFile = "pic_Chap1.jpg"; // Assign the variables
masterChapter.strChapTitle = "ABCD"; // so they can be read
trace(masterChapter.picFile, masterChapter.strChapTitle); // Should trace pic_Chap1.jpg ABCD
If you add the following method to your class:
public function test():void {
trace(picFile, strChapTitle);
}
Then call masterChapter.test() it will successfully trace those two properties. So yes, the class can read its properties.
Make the var you use in your main class public static vars.
OK!
I solved the mystery.
I put two traces. one in the main MC class saying "hey, I'm inside the MC - the picFile="
and one in the put Function saying "I'm putting this file into picFile:"
well this is what I've got:
hey, I'm inside the MC - the picFile=null
I'm putting this file into picFile:image.jpg
got it!?! at the moment I asked him to give birth to an instance of the MC (even before putting it on stage - just defining the object (with this line:)
var masterChapter:mc_masterChapter = new mc_masterChapter;
it allready run the class, so of course that in this stage the parameters were not defined allready and were null.
the definition code came right after that line (in the main.as)
masterChapter.pic="pic_Chap1.jpg";
so what I did, was to move all the code from the main class of the MC object to a public function inside the same package called init(). Then I called this function manually from the parent main class.
By that I can decide when to call it (after I declare all the parameters of course).
That's it.
god is hiding in the small details : )
tnx for all the helpers.
Possibly a better solution would be to use a getter/setter pair, so you can know at the exact moment the properties are set:
protected var _picFile:String:
public function get picFile():String {
return _picFile;
}
public function set picFile(value:String):void {
if (value != _picFile) {
_picFile=value;
trace('picFile set to', _picFile);
}
}
Related
I am creating a platformer in flash as3 and i want to pass the var Score for my score from Scene 1 to the next. However, I realized the best way to do this was to store the score inside a class, but I am having trouble referencing the variable inside the scenes. Please help. This is the code currently inside the class
package file_as{
public class CS{
public function CS(){
public var Score:Number = 0;
}
}
}
I tried to reference the score in scene in the frame containing my code my stating
CS.Score
But that didn't work so I'm lost.
To access it by doing CS.Score you would need to make that property static.
Static vars/methods belong to the class itself (CS in this case), if not static, they belong to instances of that class (eg var csInstance:CS = new CS(); csInstance.Score = 6;)
Here is how to make it static:
package file_as{
public class CS{
public static var Score:Number = 0;
}
}
As an aside, your current class code should be throwing an error, as you can't have the public/private keywords inside a function. Also, since you defined the var inside a function (the constructor in your case) it would only be available in that function. Notice how in my example above the var definition is at the class level.
All this said, I believe that if you defined a score var on your main timeline, it should be available across different scenes.
Kind of new Actionscript and I'm just trying to make a simple tamagoci game. I've wrote all the code out but and receiving no compiler errors but for some reason I'm also not receiving any output messages for my mouse event listeners. Here is all my code, I really can't find the problem and any help would be greatly appreciated. Thanks.
package{
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class Main extends MovieClip{
public var feedButton:MovieClip;
public var tamagoci:MovieClip;
public var disButton:MovieClip;
public var dietButton:MovieClip;
public function Main() {
this.init();
}
private function init():void {
this.feedButton.addEventListener(MouseEvent.MOUSE_DOWN, onfeedMouseDownHandler);
this.disButton.addEventListener(MouseEvent.MOUSE_DOWN, ondisMouseDownHandler);
this.dietButton.addEventListener(MouseEvent.MOUSE_DOWN, ondietMouseDownHandler);
}
private function onfeedMouseDownHandler(event:MouseEvent)void{
this.tamagoci.scaleX += 0.1;
this.tamagoci.scaleY += 0.1;
}
private function ondisMouseDownHandler(event:MouseEvent)void{
this.tamagoci.gotoAndPlay(5);
}
private function ondietMouseDownHandler(event:MouseEvent)void{
this.tamagoci.scaleX -= 0.1;
this.tamagoci.scaleY -= 0.1;
}
Are you using Flash Professional?
You're declaring your variable types in your class here;
public var feedButton:MovieClip;
public var tamagoci:MovieClip;
public var disButton:MovieClip;
public var dietButton:MovieClip;
But then in your constructor, all you are doing is running init();
public function Main() {
this.init();
}
So, this could one of a few things. The most likely is that you have declared your variables, but you haven't initialised them. You've created the variables to hold your objects, but according to your code, they're empty. More specifically, a variable or class property that doesn't assign an object to a variable of an object type will contain a default value of null.
You could prove this in your code by simply putting a condition inside your init(); method;
if(tamagoci == null){
trace("I haven't been assigned an object of type class yet!")
}
So it could be 1 of these 3 things:
1: If you have written your own classes for these class properties/variables, then you need to instantiate them with the new keyword. The general syntax is;
variable_name = new ClassName(parameter_1, parameter_2);
If you are using classes you have written yourself, you have to create an instance of the object, assign it to a variable, and then add it to the stage using addChild();. For example, lets say you've written your own Tamagoci class;
tamagoci = new Tamagoci();
tamagoci.x = 100; // set the x location
tamagoci.y = 200; // set the y location
addChild(tamagoci);
Notice the use of Tamagoci. This is just an example, but this is the class name, which shouldn't be confused with variable/property name. It could just have easily been;
tamagoci = new MovieClip();
But then, this is just an empty MovieClip. It needs a property to display on the screen. A Shape, A Bitmap, or another container class object like MovieClip or Sprite (container classes allow you to nest display objects inside them). But on a basic level, it must contain a visual component to appear on the stage.
2:
Have you made Main your document class? This is the class which will get automatically called when your Flash movie plays. To set this, click on your stage, and in the properties dialogue box on the right, under PUBLISH, type in the name of your class, which is "Main".
3:
If you have created MovieClips in your library in Flash Professional, then you need to go to your library, right click the MovieClips, and select properties. From there, you need to make sure Export for Actionscript is ticked.
Now, if you click on your MovieClips on the stage, then open the Properties tab in the top right of Flash Professional's default layout, then right at the top should be a text field, and if you hover over it, Instance name will pop up as a tool tip. This is where you name your stage objects. Once that is done, you have access to them in your timeline.
If this is how you've done this, then you don't need to declare the variables in your main class, as they are already declared on your stage by Flash Professional and instantiated automatically.
In AS3 - I use a generic button handler to deal with on-click events on a movie clip object. For the last 4 hours I’ve been trying to add an image to this movie clip (see * * *) object.
The code (I cut and pasted a bit but this all compiles without any errors)
btPlay = new mcButtonPlay(this,"ClickMe",GameImage); // GameImage is an BitmapData object
public class mcButtonPlay extends navigationButtonHandler {
public function mcButtonPlay(Parent:MovieClip,Text:String,GameImage:BitmapData) {
super(Text);
if (GameImage != null) {
var ImageBitMap:Bitmap = new Bitmap(GameImage);
this.addChild(ImageBitMap); // * * * This doesn’t show
Parent.addChild(ImageBitMap); // Works just to test the image
}
}
}
public class navigationButtonHandler extends MovieClip {
public function navigationButtonHandler(Text:String) {
ChangeButtonTargetText(Text);
Parent.addChild(this);
}
}
public class navigationButtonHandler extends MovieClip {
public function navigationButtonHandler(Text:String) {
ChangeButtonTargetText(Text);
Parent.addChild(this); //<--------????
}
}
where does Parent come from in the above piece of code copied from the question? It would seem the navigationButtonHandler class never gets added to the stage because it doesn't get a Parent? So the extended class also is never added to the stage which would be why your image is never shown if you addChild it to your mcButtonPlay class.
Your extended constructor DOES pass a Parent parameter but the base class doesn't. That seems weird to me and should not compile. Or are you doing some static things behind the scenes?
And get to work on your capitalization style as mentioned in the comments. It's really a lot easier to read and find errors if you follow common conventions!
this.addChild(ImageBitMap); // * * * This doesn’t show
Parent.addChild(ImageBitMap); // Works just to test the image
With this code, ImageBitMap is being removed from 'this' and placed in 'Parent', so you will never see it in 'this'.
Remove that second line and tell me if it's still working.
Edit:
Are you adding btPlay to the stage or display hierarchy?
eg.
btPlay = new mcButtonPlay(this,"ClickMe",GameImage);
this.addChild(btPlay);
Managed to fix it by swapping the super and add child logic around:
public class mcButtonPlay extends navigationButtonHandler {
public function mcButtonPlay(Parent:MovieClip,Text:String,GameImage:BitmapData) {
if (GameImage != null) {
var ImageBitMap:Bitmap = new Bitmap(GameImage);
this.addChild(ImageBitMap); // * * * This doesn’t show
Parent.addChild(ImageBitMap); // Works just to test the image
}
super(Text);
}
}
No idea why though!
how can i call public functions or vars of a sprite class from another class (or frame script)? i keep getting 1061: Call to a possibly undefined method getSide through a reference with static type flash.display:Sprite.
//Framescript
var a:Sprite = new customRect();
addChild(a);
a.getSide();
//.as file
package
{
import flash.display.Sprite;
public class customRect extends Sprite
{
public var side:Number;
private function customRect()
{
var box:Sprite = new Sprite();
box.graphics.beginFill();
box.graphics.drawRect(0, 0, 200, 200);
box.graphics.endFill();
side = box.width;
}
public function getSide():void
{
trace(side);
}
}
}
You'll need to type the other class as whatever type of class it is. Sprite doesn't, by default, have whatever property you're trying to access, so you can't just do mysprite.myRandomVariableName. However, if you happen to know mysprite is really of type MyClass then you can do MyClass(mysprite).myRandomVariableName or (mysprite as MyClass).myRandomVariableName. When using the as keyword, note that the typed mysprite will evaluate to null if mysprite is not really of type MyClass. Trying to type mySprite to MyClass using the prior method will throw an error if mysprite is not of type MyClass.
Alternatively, I believe you can use square brackets to access a sprite's dynamic properties (i.e. mysprite['myRandomVariableName'], however it's really better practice to strongly type your objects.
//edit, since you posted a code sample:
All you need here is:
var a:CustomRect = new CustomRect();//note that since CustomRect is a class name, it should be captialized.
Are you trying to call actual methods of the Sprite class or ones that you've added to a subclass of Sprite? My guess is that you need to cast the variable to the actual class that you are using. So instead of:
someReference.yourFunction();
you could try:
YourClass(someReference).yourFunction();
... this is only needed if you do not control the typing of someReference - if you do you can simply define it using var someReference:YourClass to make it known to the compiler that is is a var of YourClass type, and not of Sprite.
UPDATE after your code example was added, change:
var a:Sprite = new customRect();
to
var a:customRect = new customRect();
so the compiler knows it is a customRect and not a 'general' Sprite.
as an aside: it is custom to start classnames with an uppercase letter: so use CustomRect instead of customRect.
I've got a AS3 program with a Main.as custom class.
In this class I load an instance of a 'menu' movieclip which has simpleButton instances inside... How do I access the Main class public functions by the menu movieclip buttons?
I.e. Menu button -> gotoPage(5); (which is a Main public function)
If I try to access the Main function with the above statement, it gives
"1180: Call to a possibly undefined method gotoPage.
Create a static method called GetMain() on the Main class that would return the instance of Main (Main should be a singleton).
package whatever
{
public class Main
{
private static var _instance:Main = null;
public static function getMain():Main
{
return _instance;
}
// Main constructor
function Main(..):void
{
_instance = this;
}
}
}
To refer to the instance of Main() from your Menu class, you could use:
Main.getMain().gotoPage(5);
You want to do this with events. If your menu movieclip is a child of Main.as as you say, name the instance buttons inside of the menu movieclip, and set up the listeners in Main.as:
1) Put the below code in the constructor: public function Main(){...
menu.button_a.addEventListener(MouseEvent.CLICK, onButtonClick);
menu.button_b.addEventListener(MouseEvent.CLICK, onButtonClick);
2) and then write the onButtonClick function in Main.as
private function onButtonClick(e:MouseEvent):void{
switch(e.currentTarget.name){
case "button_a":
//call the Main.as function you want here
break;
case "button_b":
//call a different Main.as function
break;
}
ruedaminute's answer on dispatching events from the buttons and having main process those events is by far the best way to handle this, but there are many ways to do this in as3 - but try to use the aforementioned technique. Some of the other techniques.
Make a function in Main such as public function GotoPage(iPageNum:int):void{}
from a button - try this._parent.GotoPage(1);
but this._parent might not be main, do a trace(this._parent), and keep trying
it might end up being
this._parent._parent._parent.GotoPage(1) depending on your display tree hierachry.
Again, this is REALLY bad OOP practices, but well, it will work.
Another tecnique - use a singleton for main- looks like u already are - add that same public method, then from the button click, you could do Main.getMain().GotoPage(1);
That is a bit better, in that you can change the display tree and not have to figure out where the heck Main is in the display tree, but singletons also are discouraged for a variety of reasons, but in this case I would say it makes since.
Good Luck!
~ JT