When moving to Flash CC, the following problem occurred in my flash project.
Consider this class definition:
public class Test extends MovieClip {
[Inspectable(type="String", defaultValue="val")]
public var param :String;
public function Test() {
trace(param);
}
}
I have a symbol "Symbol 1" which (via the Library panels Properties) is linked to the class Test and (via the Component Definition) is also set to the class Test, and this dialog box displays the parameter "param" with value "val". I have an instance of Symbol 1 on the Scene.
The parameter "param" appears in the properties of this instance, with the value "val", as expected.
The only problem is that during runtime, the value of the parameter "param" is equal to null, as confirmed during the execution of the classes constructor, which outputs "null".
Does anyone know why this is happening?
The Inspectable tag is needed by Flash to populate the component properties panel in order to set values manually. These parameters, both default and user input, are not available at instantiation, but they are available only at the following frame.
In order to have default values at instantiation you must set the default value also on the variable itself.
[Inspectable(type="String", defaultValue="val")]
public var param :String = "val";
Also, before you go crazy accessing values inserted with property inspector, remember to add an enter frame event before accessing those values.
What I usually do in my components:
1 - Populate default in both inspectable and variable
2 - On instantiation, if a parameters object is received, then I know it's instantiated in code and values are inside the parameters object
3 - If a parameters object is not received, then instantiation is done on timeline visually, therefore I access properties on next frame
Related
(This may be too localized an issue but I will try to generalize it)
Question: If a property setteris marked as Bindable, will it not get called if the new value is the same as the old value?
I am seeing the above behavior in a legacy project I have inherited: the setter is not getting called. If I don't declare the setter as Bindable then the setter is called no matter what the new value is.
Can anyone confirm that the above is the way things are designed to work with Binding?
This project uses Binding all over the place and there are no comments in the code so it is hard to tell what the dependencies are and which parts of the code depend on particular bindings. I'm trying to avoid making major changes but I also don't want to waste time trying to work around something which should be refactored.
The property is bound:
[Bindable]
protected var _source:AolMediaFile;
The setter is bound:
[Bindable]
public function set source(file:AolMediaFile):void{
_source = file;
// do some stuff with file
}
The setter should only get called if the event source is [Bindable]. Data binding is basically a chain of events dispatched from source to target in a variety of scenarios. When you declare your property or setter as [Bindable], that will basically change nothing in the behaviour in terms of side effects, as events are dispatched and listeners are generated. For example:
<your:Component source="{any.source.aolMediaFile}" />
Only when any, source and aolMediaFile are declared [Bindable], source would be invoked. Having source declared as a [Bindable] property is only interesting, if a second component would be depending on your component's state
<your:Component id="yourComponent" source="{any.source.aolMediaFile}" />
<s:TextField text="{yourComponent.source}" />
If you would want to bind to a property of AolMediaFile, then the class or the specific property has to be be [Bindable] as well.
Usually the compiler prints warnings, if bindings can't be generated:
warning: unable to bind to property 'source' on class 'Object'
(class is not an IEventDispatcher)
So check the source object, which are the source's host object's dependency and the compiler warnings.
So digging around here a bit more I came across this question: Flex: Help me understand data Binding on getters and setters which describes the code generated by declaring a setter or getter Bindable
So apparently in the generated code there is a check to see if the value is different:
public function set name(value:String)
{
if (_name == value)
return;
_name = value;
dispatchEvent(new Event("nameChanged"));
}
I've been searching for this for few hours now and didn't get any result. I have a script called GameSetup.js that is attached to an empty game object (named GM) . It holds references to my current camera and has functions to get screen width and other stuff. I'd like to access these functions ( and variables) from other scripts. so for example I have another empty game object called "Blocks", one of its components is BlockGenerator.js , which has BlockGenerator() function. I want to be able to use screenWidth() in BlockGenerator() like this:
BlockGenerator.js
BlockGenerator(){
var Blocknumber : int = GameSetup.ScreenWidth / blockWidth;
}
GameSetup.js
function ScreenWidth() : float{
var screenWidth : float = (mainCam.ScreenToWorldPoint(new Vector3(Screen.width,0f, 0f)).x)* 2;
return screenWidth;
of course GameSetup is not recognized in BlockGenerator.js if I use GetComponent(), for example. I'm not sure if I can drag GM game object in the inspector and pass it to BlockGenerator.js , I haven't tried. but the thing is, it makes the game script very complicated for no good reason. how can I setup and access global functions and variables?
In the class that holds the BlockGenerator method you need to define a public variable of type GameSetup. Then in the inspector drag the object whose instance variables you wish to access. After that you can access the object in your BlockGenerator method and call its methods and access its instance variables.
Another way is to find the object by tag in BlockGenerator via https://docs.unity3d.com/Documentation/ScriptReference/GameObject.FindGameObjectsWithTag.html or search by type with http://docs.unity3d.com/Documentation/ScriptReference/Object.FindObjectOfType.html.
Ok, so this might be me being pendantic but I need to know the best way to do something:
(This is psudocode, not actual code. Actual code is huge)
I basically have in my package a class that goes like this:
internal class charsys extends DisplayObject {
Bunch of Variables
a few functions
}
I another class which I intend to add to the timeline I want to create a function like this:
public class charlist {
var list:Array = new Array();
var clock:Timer = new Timer(6000);
var temp:charsys;
function addObj(MC:DisplayObject, otherprops:int) {
temp=MC;
temp.props = otherprops;
list.push(temp)
}
function moveabout(e: event) {
stuff to move the items in list
}
function charlist() {
stuff to initialize the timers and handle them.
}
}
So the question is, is my method of populating this array a valid method of doing it, is there an easier way, can they inherit like this and do I even need to pass the objects like I am?
(Still writing the package, don't know if it works at all)
Yes, you can pass an object into a function, but you should be careful of what you are planning to do with that object inside that function. Say, if you are planning to pass only charsys objects, you write the function header as such:
function addObj(MC:charsys, otherprops:int) {
Note, the type is directly put into the function header. This way Flash compiler will be able to do many things.
First, it will query the function body for whether it refers to valid properties of a passed instance. Say, your charsys object does not have a props property, but has a prop property, this typing error will be immediately caught and reported. Also if that props is, for example, an int, and you are trying to assign a String value to it, you will again be notified.
Second, wherever you use that function, Flash compiler will statically check if an instance of correct type charsys is passed into the function, so if there is no charsys or its subclass, a compilation error is thrown.
And third, this helps YOU to learn how to provide correct types for functions, and not rely on dynamic classes like MovieClip, which can have a property of nearly any name assigned to anything, and this property's existence is not checked at compile time, possibly introducing nasty bugs with NaNs appearing from nowhere, or some elements not being displayed, etc.
About common usage of such methods - they can indeed be used to create/manage a group of similar objects of one class, to the extent of altering every possible property of them based on their corresponding values. While default values for properties are occasionally needed, these functions can be used to slightly (or not so slightly) alter them based on extra information. For example, I have a function that generates a ready-to-place TextField object, complete with formatting and altered default settings (multiline=true etc), which is then aligned and placed as I need it to be. You cannot alter default values in the TextField class, so you can use such a function to tailor a new text field object to your needs.
Hope this helps.
This would work, I think I would assign values to the properties of the charsys object before passing it into the add method though, rather than passing the properties and having a different class do the property assignment. If you have some common properties they could either have defaults in charsys class definition or you could set literals in the addObj method.
I created this simple example
because I was using a more complex class, a menu item that I wanted to initialise all the settings in the Main class and then add it in in the Game class (and updating it) when needed (both classes are separate)
Class: Main (document class, is (ideally) where everything is initialised/created)
public class Main extends MovieClip
{
//testing passing on reference to Game
private var testBitmap:Bitmap;
private var testBitmapData:BitmapData;
private var testArray:Array;
public function Main():void
{
testBitmapData = new BitmapData(256, 256, false, 0xCCDDEE);
testBitmap = new Bitmap(testBitmapData);
testArray = [];
testArray.push(testBitmap); //Array for reference
game = new Game(540, 960, testArray);
//create Game class, pass reference to Object
game.x = 0;
game.y = 0;
}
}
Class: Game (created by document class, is (ideally) where everything runs)
public class Game extends MovieClip
{
private var testingArray:Array
public function Game(gameWidth:int, gameHeight:int, testArray:Array):void
{
this.testingArray = testArray; //assign to local Array and access
addChild(testingArray[0]);
//addChild to Game from an item intialised in Main, doesn't work >___<
}
}
.
.
.
the thing is, in my original Game class; it receives an initial bundle of cached BitmapData and a list Array that tells it which BitmapData it needs to cycle through
cut-down here (and that reference only for updating works (if I addedChild in Main already):
public function Game(gameWidth:int, gameHeight:int, cachedBitmapClipArray:Array)
{
this.cachedBitmapClipArray = cachedBitmapClipArray;
private function update():void
{
for each (tempCachedBitmapClip in cachedBitmapClipArray)
{
tempCachedBitmapClip.updateCurrentTile();
//but updating through the reference to an item initialised in Main works !!
}
}
}
.
how do I make the reference and passed in objects (or have access to) behave as in the original instance ?? (being able to addChild)
i.e. can objects cross 'scopes' (??) or should objects only be controlled (instantiated) in the class where they have been initialised
Well to answer the last question, yes objects can be passed from one object to another. I'm having a hard time understanding what exactly the problem is though. In generic programming terms Object or any other complex type are passed by reference, primitive types are also passed by reference but the internals of the AVM handle them in such a way as to treat them as passed by value. For a pretty clear (in my eyes at least) explanation of how arguments are passed via function/method calls, read here:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f56.html
Check out other areas in the tree navigation on the left for more details on the language itself.
One thing to note though I think the compiler will work around this error, in the first bit of code you posted Game has a return value of :void for a constructor there should be no declared return type since it should be implicitly typed as whatever the class is.
To add some explanation in my own words regarding pass by reference or pass by value. Pass by value means that the value of the object, that is the bytes stored at the location pointed to by the variable are actually copied to a new memory location which is then used. What this means in practice is they are not the same bytes of memory but rather they are two separate memory locations each with the same value stored in them, modification of one value after the passing doesn't affect the original. Pass by reference is to say you pass the memory location therefore no new memory for the value is allocated, both values are actually pointing to the same memory location (the pointer to them itself may be different but that pointers both point to the same location in memory). In this case the objects are the same.
What you're doing is advisable, dividing the labor and enapsulating particular types of functionality in classes does make the code easier to work with. I think the only problem would be if the Game object itself is never added as a child to something in the display tree (something that is attached to the stage). It appears you're creating a new Game and setting it's position but never adding it as a child to the stage, then adding anything to Game is never a part of the display tree.
For some time now I have been making a very easy game for iPhone in flash using as3.
Recently I came in contact with a small problem, which is why I am posting this!
The problem:
I have a superclass from which everything derives. In the superclass I initiate and place an Object on stage.
1. var myObject:typeA = new typeA();
2. stage.addChild(myObject);
As you can see this object follows the class 'typeA' which, ocf, has its own actionscript file. Inside of this file I have declared a global variable of type string.
What I want to do is change the varbiable on the new object from the superclass. Therefor I tried as following:
1. myObject.myVariable = 'someSortOfString';
Unfortunatly it didn't work and so I wonder how to do this; change a subclass' variable from the superclass.
You need to declare the variable that is being accessed from the subclass as protected (Or public), by default the variable is private so only accesible by the superclass.
e.g. protected var myObject:typeA = new typeA();
BTW did you mean change the superclass variable from the subclass instead of "change the subclass variable from the superclass"?