How to use addChild() w/o extension from another class? - class

Is it possible to use addChild() without 'extends' from another Class ?
It's strange, that i need to extension from another classes to use it ... but maybe its my lack of knowledge in as3 ...
Main:
public class Main extends Sprite
{
private var sprite:Sprite = new Sprite();
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);
// entry point
var myVar:MyClass = new Myclass();
addChild(myVar);
}
}
MyClass:
public class MyClass
{
private var sprite:Sprite = new Sprite();
public function MyClass()
{
sprite.graphics.lineStyle(1, 0x990000, 1);
sprite.graphics.drawRoundRect(5, 5, 500, 150, 10, 10);
addChild(sprite);
}
}

addChild is method that add's DisplayObject to DisplayObjectContainer, so yes, you must extend your custom classes if you want to see it on screen
futher reading: http://help.adobe.com/en_US/as3/dev/WS5b3ccc516d4fbf351e63e3d118a9b90204-7e3e.html
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObjectContainer.html

I looks like you're trying to do this:
public class MyClass
{
private var sprite:Sprite;
public function MyClass(container:MovieClip)
// ^^^^^^^^^ Take a reference to a container to add children to.
{
sprite = new Sprite()
sprite.graphics.lineStyle(1, 0x990000, 1);
sprite.graphics.drawRoundRect(5, 5, 500, 150, 10, 10);
container.addChild(sprite);
// ^^^^^^ Add internal sprite to the referenced container.
}
}
Where you provide a container to add children to.
Meaning your Main class will simply pass a reference to itself to your MyClass instance.
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
var myVar:MyClass = new MyClass(this);
// ^^^^ Simply pass the main class as the container.
}
Another option is to simply expose sprite from MyClass and then use:
addChild(myVar.sprite);
In your Main class.

The simple answer to your question is: no, a custom class cannot addChild without extending a subclass of DisplayObjectContainer. The method addChild() and its related methods are defined in DisplayObjectContainer and only subclasses of it can use them.
You often see the method addChild() used without a calling object (ex: theobject.addChild()) but that's only because the keyword "this" is implied. In reality addChild() is always called by a DisplayObjectContainer instance.

Related

String Constructor not working in unity c#

Salutations, this'll be brief.
So, I tried to change the name of one the hero struct in my game, but it doesn't update, neither in the inspector nor in the de facto code.
I can call the constructor just fine, and if I print the heroname before and after (in the constructor), it tells me the new name. However, It does not change.
Here is the (simplified) code:
//This already has a name in the inspector that I want to override
public List<TroopStat> PlayerHeroStats = new List<TroopStat>();
void Start () {
PlayerHeroStats[0].ChangeTroopType();
}
[System.Serializable]
public struct TroopStat {
public string nameOfTroop;
public void ChangeTroopType() {
nameOfTroop = "Blabla";
}
}
Any ideas?
Structs are value types. You need to assign a new struct or use class instead.
This should work:
void Start () {
TroopStat stat = PlayerHeroStats[0];
stat.ChangeTroopType();
PlayerHeroStats[0] = stat;
}
Or make the TroopStat a class.
You can read more about it here.

Why is it not possible to access static fields of a class via Type.getClass()?

In Haxe, it is possible to get the class of an object with the following function:
Type.getClass(myObject);
If the object myObject is an instance of the class myClass, which contains a static field, I should be able to access this static field:
class MyClass
{
public static myStaticField:Int = 5;
}
public var myObject = new MyClass();
//expected trace: "5"
trace (Type.getClass(myObject).myStaticfield);
But the result is:
"Class <MyClass> has no field myStaticField."
Any idea why?
You need to use reflection to get such value:
class Test {
#:keep public static var value = 5;
static function main() {
var test = new Test();
var v = Reflect.field(Type.getClass(test), "value");
trace(v);
}
public function new() {}
}
Note that to prevent DCE (dead code elimination) I had to mark the static var with #:keep. Normally DCE is going to suppress that variable because it is never referred directly.
Working example here: http://try.haxe.org/#C1612
Try the Reflect class (Specifically the callMethod or getProperty functions).

How can I address a script I don't know the type of?

My game uses a variety of different game modes, and I'd like to spawn a different GameController script at the beginning of the scene depending on the game mode selected. Then other items (e.g., Enemies), would reference the main GameController, whether that be GameController_Mode1, GameController_Mode2, etc. But how can I have other objects referencing this if I don't know the type?
Unity iOS requires strict unityscript typing, so I can't use duck typing to get around this.
You can do this the same way you'd do it in C#, polymorphism. Derive all of your controllers from a single base Controller class. Then your GameController var can be set to any instantiation of a derived controller (see Start() in the example below).
Here is a quick example using a simple controller:
#pragma strict
var controller : MyController;
class MyController {
var data : int;
public function MyController(){
this.data = 42;
}
public function Print(){
Debug.Log("Controller: " + this.data);
}
}
class MyController1 extends MyController {
public function MyController1(){
this.data = 43;
}
public function Print(){
Debug.Log("Controller1: " + this.data);
}
}
class MyController2 extends MyController {
public function MyController2(){
this.data = 44;
}
public function Print(){
Debug.Log("Controller2: " + this.data);
}
}
function Start () {
controller = new MyController();
controller.Print(); // prints Controller: 42
controller = new MyController1();
controller.Print(); // prints Controller1: 43
controller = new MyController2();
controller.Print(); // prints Controller2: 44
}
I'm making any assumption that your gamecontrollers share function names and that the only difference is the code in each function.
[Update]
Regarding Heisenbug's comment below: You can use GetComponent to get the base class controller if your controller is a component.
Baseclass(BaseController.js):
class BaseController extends MonoBehaviour{
public function Print(){
Debug.Log("BaseController");
}
}
Extended class(Controller1.js):
class Controller1 extends BaseController {
public function Print(){
Debug.Log("Controller1: " + this.data);
}
}
Test:
var controller : BaseController;
controller = gameObject.GetComponent("BaseController"); //.GetComponent(BaseController) also works
controller.Print(); // will print "Controller1" if actual attached component is a Controller1 type
While it looks like there are some good answers already but it is worth mentioning Unity's SendMessage system. It is a really simple approach if all you need to do is call functions on the other object SendMessage.
http://docs.unity3d.com/Documentation/ScriptReference/GameObject.SendMessage.html
In short you can use the following syntax:
TargetGameObject.SendMessage("targetFunction", argument, SendMessageOptions.DontRequireReceiver);
You can also use SendMessage to call javascript functions from C# scripts or vice versa.

is it possible to put Class in a variable and access the class's static variables and functions in actionscript3?

Say I had the following class
public class Scene{
public static var title="new scene";
public function Scene(){}
public static function start() { trace("scene started"); }
}
How can you access the Scene class's static variables and functions like this?
var i:Class = Scene;
trace(i.title);
i.start();
I'm trying to figure out how variables assigned with Class work in actionscript.
Any tips would be welcome. Thanks.
Static methods are called from the class:
trace(Scene.title);
Scene.start();
Singleton patterns enable constructor, local reference, and potentially abstraction through interface classes.
Example of Scene as a singleton:
package
{
public class Scene
{
private static var instance:Scene = new Scene();
public static function getInstance():Scene
{
return instance;
}
public var title:String = "new scene";
public function Scene()
{
if (instance)
throw new Error("Scene is a singleton and can only be accessed through Scene.getInstance()");
}
public function start():void
{
trace("scene started.");
}
}
}
Your example implementation would now be:
var i:Scene = Scene.getInstance();
trace(i.title);
i.start();
This is how you can access the dynamic class (Scene) & it's properties / methods :
var myDynamicClasses:Array = [Scene]; // Required
var i:Class = Class(getDefinitionByName("Scene"));
trace(i.title);
i.start.call();
This could throw an error, if the first line is not included. Because, when the compiler notices the class Scene (not the one from adobe's package) is not being used it ignores it. Thus it would be not available for dynamic initialization.
We could force the compiler to include these classes by putting these class names in variables or declare an array as above as a quick hack.
If you have many dynamic classes, you could add a reference to them in this array & each class will be included by the compiler for dynamic initialization.
var i:Class = Scene;
trace(i.title);
Should throw an error because the compiler can no longer assume that i is a scene when it gets to line 2. If you were to coerce the Class object, it should work.
var i:Class = Scene;
trace((Scene(Class).title);

Creating an object passing a lambda expression to the constructor

I have an object with a number of properties.
I want to be able to assign some of these properties when I call the constructor.
The obvious solution is to either have a constructor that takes a parameter for each of the properties, but that's nasty when there are lots. Another solution would be to create overloads that each take a subset of property values, but I could end up with dozens of overloads.
So I thought, wouldn't it be nice if I could say..
MyObject x = new MyObject(o => o.Property1 = "ABC", o.PropertyN = xx, ...);
The problem is, I'm too dim to work out how to do it.
Do you know?
C# 3 allows you to do this with its object initializer syntax.
Here is an example:
using System;
class Program
{
static void Main()
{
Foo foo = new Foo { Bar = "bar" };
}
}
class Foo
{
public String Bar { get; set; }
}
The way this works is that the compiler creates an instance of the class with compiler-generated name (like <>g__initLocal0). Then the compiler takes each property that you initialize and sets the value of the property.
Basically the compiler translates the Main method above to something like this:
static void Main()
{
// Create an instance of "Foo".
Foo <>g__initLocal0 = new Foo();
// Set the property.
<>g__initLocal0.Bar = "bar";
// Now create my "Foo" instance and set it
// equal to the compiler's instance which
// has the property set.
Foo foo = <>g__initLocal0;
}
The object initializer syntax is the easiest to use and requires no extra code for the constructor.
However, if you need to do something more complex, like call methods, you could have a constructor that takes an Action param to perform the population of the object.
public class MyClass
{
public MyClass(Action<MyClass> populator)
{
populator.Invoke(this);
}
public int MyInt { get; set; }
public void DoSomething()
{
Console.WriteLine(this.MyInt);
}
}
Now you can use it like so.
var x = new MyClass(mc => { mc.MyInt = 1; mc.DoSomething(); });
Basically what Andrew was trying to say is if you have a class (MyObject for eg) with N properties, using the Object Initializer syntax of C# 3.0, you can set any subset of the N properties as so:
MyObject x = new MyObject {Property1 = 5, Property4 = "test", PropertyN = 6.7};
You can set any of the properties / fields that way./
class MyObject
{
public MyObject(params Action<MyObject>[]inputs)
{
foreach(Action<MyObject> input in inputs)
{
input(this);
}
}
}
I may have the function generic style wrong, but I think this is sort of what you're describing.