Static function in base class not wanting to call member functions on subclasses if using Flash Builder 4.7, instead of 4.6 - actionscript-3

Since yesterday, I've been trying to port an ActionScript Mobile project from Flash Builder 4.6 to Flash Builder 4.7, and I've run into a little bit of a problem that's probably a compiler bug. In FB 4.6, this works:
Temp.as:
package
{
import flash.display.Sprite;
public class Temp extends Sprite
{
public function Temp()
{
new StartMenu();
}
}
}
Screen1.as:
package
{
import flash.display.*;
internal class Screen1 extends Sprite
{
private static var m_vScreens:Vector.<Screen1> = new Vector.<Screen1>();
public function Screen1()
{
m_vScreens.push(this);
onScreenSizeDetermined();return;
var strFunction:String = "useSmallPortraitLayout";
for each (var screen:Screen1 in m_vScreens)
{
trace(1)
screen[strFunction]();
}
}
protected function useSmallPortraitLayout():void
{
}
private static function onScreenSizeDetermined():void
{
var strFunction:String = "useSmallPortraitLayout";
for each (var screen:Screen1 in m_vScreens)
{
trace(2)
screen[strFunction](); // Error thrown here in 4.7.
}
}
}
}
StartMenu.as:
package
{
public final class StartMenu extends Screen1
{
override protected function useSmallPortraitLayout():void
{
}
}
}
But in 4.7, it doesn't work. The error I get back is this:
ReferenceError: Error #1069: Property useSmallPortraitLayout not found on StartMenu and
there is no default value.
Now that being said, this can be fixed in one of at least two ways:
Use Flash Builder 4.6
Comment out onScreenSizeDetermined();return;, thereby using a member function to call useSmallPortraitLayout(), instead of a static function. This doesn't require using the constructor; it works just fine, as long as Screen1 is calling useSmallPortraitLayout() from pretty much any non-static method.
Unfortunately the static method will fail, even when it's called from outside the constructor and/or from a timed delay. One thing I don't specifically remember in 4.6, but I am seeing it in at least 4.7, is that using an unrelated class to call a static method directly through an instance won't compile - it has to be done in a staticky way in unrelated classes. Not that I do things like that in real code, but it does make me wonder if the relationship between static and non-static has intentionally changed.
This is probably just some trivial compiler bug specific to FB 4.7, and I would just go right back to 4.6, but pure ActionScript library projects are directly supported only in 4.7. (This is a mobile project, but I was going to add a library project to the solution.)
One thing to note is the code will not compile in FB 4.7 if the static function calls useSmallPortraitLayout this way:
screen.useSmallPortraitLayout();
It has to call it dynamically for it to even compile.
Is there an easy-enough fix for this? Has there been a little bit of syntactical weirdness that 4.6 has simply been overlooking this whole time? What's wrong, and what's a good solution/work-around?
UPDATE
If worst comes to worst, it does seem to work to partially replace the Vector.<Screen1> with a Vector.<Function>, and then just make calls to the members of the function vector, instead of to functions of the members of the Screen1 vector. (This is simplified from production code.) But that's just a fallback.
Also, something I wasn't paying a lot of attention to previously (specifically as far as this one problem goes), but BotMaster kind of brought it to my attention, is that in the process of going from FB 4.6 to FB 4.7, I also went from AIR 3.1 to AIR 3.4.

This is more a scope issue imo. Protected method can only be called within the instance scope and not within a static scope. Of course changing the modifier to public fixes the issue here. PO might argue that protected is wanted here but in reality if there is intention of directly calling a method on an instance outside the scope of that instance then logically that method needs to be public.
Btw FB 4.6 compiler is provided by the used AIR/FLEX SDK and so cannot behave differently from FB 4.7 using the same SDK.

Flash Builder 4.7 uses ASC 2.0 to compile ActionScript projects. From the release notes, emphasis added:
ASC 2.0 is a new compiler for ActionScript® 3.0 (AS3). It has stricter
adherence to the AS3 language specification, includes compilation
performance improvements, is more stable under memory pressure, and
contains some demonstration optimizations that can be optionally
enabled (in-lining, dead code elimination).
I suspect that the compiler sees useSmallPortraitLayout() is not referenced in your original code, and is eliminated from the ABC output.

Related

Call platform specific code from core project

I just Implemented ads for Android in my game using this guide.
It works fine, I have an interface in my core project that the Android Activity implements.
However my problem is that you need to send this implemented interface to the core project, and then pass it as a parameter to your first Screen, where you can use it, ex:
public MyGdxGame(PlatformSpecific ps) //Android class that handle fb-login and ads
{
this.ps = ps;
}
#Override
public void create ()
{
setScreen(new LoginScreen(this, ps);
}
This was fine for when I needed fb-login since I'm using that in the LoginScreen, but I want to be able to create my ads in other Screens (after a game is finished) by calling createAd-method in interface.
Do I have to keep passing ps between all the Screens just so I can use it in a Screen that only gets used quite rarely, or is there some way to get to this interface from my Screen without passing it to the constructor? Kind of like when you initiate an object, ex:
private PlatformSpecific ps = new PlatformSpecific();
Or does LibGdx have some library to support this scenario maybe? Worst case I could just pass ps between all constructors but feels like a pretty ugly solution.
Solution 1:
Store PlatformSpecific in a global static variable. That allows you to access anywhere in your code without passing it in every constructor.
Soluatio 2:
Have MyPlatformContext class which provides access to PlatformSpecific. Then pass this MyPlatformContext object to your screen constructors. If you extend your platform specific code later you do not have to change the screen constructors. Just edit MyPlatformContextMyPlatformContext class.
Pseudo code:
class MyPlatformContext {
private FacbookPlatform fb;
private AdmobPlatform admob
FacbookPlatform getFacebook() {
return fb;
}
...
}

Type was not found or was not a compile-time constant: Custom Class after switching IDEs

It seems that this is a fairly common error, but I was not able to find a solution for my exact problem. I was originally working in FlashBuilder, but my free trial expired and so I am attempting to switch to flashDevelop. Everything would build just fine in FlashBuilder, but I keep getting errors in FlashDevelop I have a custom class called MyCustomClass which extends EventDispatcher. I'm not allowed to be too specific with code, as this is for work, but I have something similar to this:
package myPackage{
import myPackage.MyCustomClass;
public class SecondClass extends EventDispatcher{
private var _fields:Vector.<MyCustomClass>;
[Bindable("fieldsChanged")]
public function get fields(): Vector.<MyCustomClass> { return _fields.slice(); }
}
}
I get the error Type was not found or was not a compile-time constant: MyCustomClass
on the fourth line of code. Any ideas?
Probably your source path is not setup in Flash Develop. In the project panel (View > Project Manager) select your source root directory (probably "src" since that is what Flash Builder creates by default) and right click and choose "Add Source Path". You can also setup your source paths in Project > Properties.. > Classpaths.

ActionScript Library Project vs. Flex Library Project

I've got couple of issues from the nature of inconsistency between FlexLib Project and AS3 Lib Project in Flash Builder 4.7, AIR SDK 15, 16 and 17, Flex SDK 4.6.
Common thing for these is that FlexLib does not allow (syntax error highlighted) to build/compile pieces of code that are allowed in regular AS3Lib Project.
Please note that examples bellow are simplified, and there are real life use cases even if it's against good practices.
Internal classes above package
internal class Before
{
public function Before(){}
}
package
{
public class Main
{
public function Main()
{
}
}
}
In Flex Library Project this code causes:
1083: Syntax error: package is unexpected.
In regular ActionScript Library project it works perfectly fine, without a single warning.
Array key type greediness
var array:Array = [Boolean, Number, XML];
for(var c:Class in array)
{
if(c is Object) { trace('test') }
}
In Flex Library Project this code causes:
1067: Implicit coercion of a value of type String to an unrelated type
Class.
In regular ActionScript Library project it works perfectly fine, without a single warning.
Constant defined class
public static const FileClass:Class = String;
public function main():void
{
if('test' is Vector.<FileClass>)
{
trace('what?');
}
}
In Flex Library Project this code causes:
1120: Access of undefined property FileClass.
In regular ActionScript Library project it works perfectly fine, without a single warning.
I'd be very thankful if someone could say a word why is this happening or could give me a clue where to look for solution.
According to this, there are two different compilers involved:
Use Legacy Compiler
For ActionScript projects, Flash Builder uses the ActionScript Compiler (ASC) by default. If you are using Adobe Flex SDK 4.6 or an earlier version of the Flex SDK, select Use Legacy Compiler to use the older compiler.
I guess that explains the difference.
The following is an attempt to work around the problem.
I'm not too much into library projects.
From what I found in resources (the link above), these projects result in a .swc file.
I'm not too much into flex either.
Flex is "just" a framework written in actionscript.
Whether your library is an actionscript library or a flex library is not really a choice of the user, but what your code does.
If your library includes some flex components, I'd say it's a flex library project.
But if it is plain old actionscript, it is an actionscript library.
Let's say your library is an actionscript library.
You compile your library into an .swc file and be done with it.
Your are the one doing that compilation step, not the user of your library. I don't think it's their concern if they could perform this compilation.
What actually concerns them is whether their project that includes your library (the .swc file) compiles. And I guess that this will be the case, because the .swc will be used, not compiled.
After all, there's no choice to be made, if it is an actionscript library, because every flex project is an actionscript project. (but every actionscript project is a flex project)
Build your library project (whatever compiler works) and see if you can use the resulting .swc file in both an actionscript and a flex project.

Type Coercion failed in 'loader' and 'loaded' applications

My main application swf file is being loaded by a simple loader swf application that is useful to break cache. In both applications I would like to have access to a singleton. I will provide you with an example to reproduce the bug. So here's our singleton:
package {
public class SingletonTest {
public static const instance:SingletonTest = new SingletonTest();
public function SingletonTest() { /* Nothing here. */ }
public function test():void {
trace("SingletonTest!");
}
}
}
In constructors of both loader and main classes I call:
SingletonTest.instance.test();
That is made in order to be sure that my singleton class code will be included in both applications. I won't provide you with loader code but it's very simple. It creates Loader instance, it creates LoaderContext supplying it with both current ApplicationDomain and SecurityDomain, etc...
But when I launch my loader application I get following error:
Main Thread (Suspended: TypeError: Error #1034: Type Coercion failed:
cannot convert SingletonTest#47a3091 to SingletonTest.)
SingletonTest$cinit
I get this error right after main application was loaded with loader. Event.COMPLETE is not dispatched yet so no handlers involved. I spent a lot of time trying to find something about application or security domains but it seems like it's not the issue because what I found next is really strange. If instead:
public static const instance:SingletonTest = new SingletonTest();
I will write:
private static var _instance:SingletonTest;
public static function get instance():SingletonTest {
if (_instance == null) _instance = new SingletonTest();
return _instance;
}
Then there will be no such error and everything will be fine. Obviously flash player is performing some unexpected behavior here. There's very few information on this issue out there. Most of people get this error because of missing loader context but as I said before here it's not the case. Some discussions on this are even left without any answers which is strange to me because I find this to be quite a common problem to be encountered when using small applcation loader.
Spent almost 12 hours trying to solve the problem. At last found the solution. In order to avoid runtime error which I provided above you need to compile your singleton class into swc-library. That's it.
In my case that singleton was providing global access to logging and only option was to switch from singleton pattern to static class. But I didn't want it very much because I really like this one-line singleton instantiation: "public static cosnt instance:MyClass = new MyClass();".

cocos2d-x c++ -> java for android

Currently I'am developing a game using cocos2d-x.
Of course, for multi-platform use.
basically I use a xcode for coding and development.
I want to attach IAP(In app purchases) separately to each coding for iPhone and Android
Problem to try to call a function of a certain class in Android that did not work.
Sources include the following:
cpp side
MyClass::invoke_init()
{
JavaVM* jvm = JniHelper::getJavaVM();
JNIEnv* env;
jvm->GetEnv((void **) &env, JNI_VERSION_1_2);
jclass cls;
jmethodID method;
cls = env->FindClass("com/joycestudios/game/SampleActivity");
method = env->GetMethodID(cls, "initFunc", "()V");
env->CallVoidMethod(cls, method);
}
java side
public class SampleActivity extends Cocos2dxActivity
{
public void initFunc()
{
Log.v("LOG_INFO", "initFunc()");
}
}
The first test as follows: I'm in progress.
build from xcode and build from build_natvie.sh and last build from eclipse.
But after run on eclipse, Just black screen and shuts down.
How to call a function of a java class?
What I looked at several samples, including also analyze the problem, I do not see any problems?
Can you tell if you find any error log?
First check if your game is working fine on android..
Den we can have a look how to call the function.
Generally for calling native method I use MessageJni class available in Cocos2d-x library.
I create my methods in MessageJni class which calls for native methods.
Its easy and convenient way of calling native methods.
Just google using MessageJni class. It will ease your work.
:)