I have a Java class which is a singleton which stores a boolean variable:
public boolean paused;
So basically I use it when the game is paused and to set it to true or false. I use this (to call the pause variable):
public static DataVariables getInstance() {
return ourInstance;
}
Everything works fine, the game stops when I use the variable, but I noticed that after minimizing my window the value suddenly turns to false and the game behaves as if it hasn't been stopped. Can anyone tell why this is?
Related
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;
}
...
}
I have a Spark Window that I use as a popup window in front of my main application. I prefer this method to the PopUp Manager. However, I run into a strange error when calling the windows close() method. In the closing event handler, I have a function which does the following
public function closeHandler(event:Event):void {
this.owner.removeChild(this);
}
The window's owner is WindowedSystemManager, but at some point during the removeChild phase, the stage becomes null, and Flex throws an error trying to close the nativeWindow because it cannot find a reference to it. Two things fix this,
Instead of calling window.close(), call window.nativeWindow.close();
Do not call this.owner.removeChild(this) in the closing handler.
I'm trying to understand what is going on, does anybody have any idea??
I have an application which will be using large numbers of assets. In order to better handle that I chose to use a registry to hold all the assets so they are accessible across the entire application:
package
{
public class SpriteRegistry
{
public static var SPRITENAME = "link to image file";
public function SpriteRegistry()
{
}
}
}
What I would like to do is create an XML document and list off the file name and link so that when the application starts, this registry creates its variables which are freely accessible from that list without me needing to hard code any content directly into it.
Specifically what I need to know is how to get the "public static" effect or how to get an equivalent effect for variables that I CAN dynamically produce.
More info:
I am using a function that loads a sprite texture into a sprite object based on a string variable called mouseAttribute:
loadGraphic(SpriteRegistry[currentAttribute+"Texture"]);
Basically it's like a painting program but for a level editor for a video game.
The problem is that I'm eventually going to have 100+ sprites that I need to application to load and then I need the loadGraphic function to still be able to point effectively to the target sprite.
The library I'm using also needs me to embed the source into a class before I can pull it into the sprite object:
[Embed(source = "/Images/GridTile.png")]
public static var gridTileTexture:Class;
The reason I'm trying to avoid an array is because it means that I will have to search through an array of 100+ objects to find one sprite every time I click a single grid on the editor. That is going to chug.
It's very simple - just use a static function, which will return the XML. So you will need to load the XML file somehow (you decide where, but your registry class should have reference to it). Something similar to this:
private static var _xml:XML;
public static function initialize(xml:XML):void {
_xml = xml;
}
public static function getXML():XML {
return _xml;
}
So you will use it like that:
SpriteRegistry.initialize(loadedXML); // done only once when you initialize your app
trace(SpriteRegistry.getXML().someValue); // someValue is directly from the XML
It's a common used strategy and most of the times you would have something like an app initializer - something to load and instantiate all the things, then pass them to some registries that keep them stored for faster and global usage.
Edit:
After reading your further comments, I can't see any big change - everything would be ok with this resolution.
If you are worried about the 'need to search through array' - just do it as an object! This way you will be able to directly access the proper one using a key exactly like you pointed:
private static var _registry:Object;
public static function initialize(xml:XML):void {
// loop through xml and insert items
_registry[key] = resource;
}
public static function getResource(id):Object {
return _registry[id];
}
This way you can use it like:
SpriteRegistry.getResource(currentAttribute+"Texture");
My personal opinion is that you should avoid statics wherever possible. Instead, you should just create a single instance and provide it through dependency injection where needed.
If you were to go with that approach, you could do something like:
public function getSprite(spriteName:String):Class{
return this[spriteName];
}
or
public function getSprite(spriteName:String):Class{
return yourDictionaryOrObject[spriteName];//I'd implement it this way
}
Otherwise you could go with something like:
public static function getSprite(spriteName):Class{
return ThisHonkingBigUnnchangeableClassname[spriteName];
}
What I would not do is create a Dictionary in a static-only Class, because you're almost inevitably going to wind up with global mutable state.
Discussion, per request
Why would you want to create an instance and pass it, rather than hard-code a reference to a specific Class? A lot of the answers are covered in the global mutable state link above, but here are some that are specific to this kind of problem:
Flexibility. Say you build everything with the idea that you'd only have one set of resources being used in parallel, then you discover you need more than one--for example you might need one for color blind users, or multiple languages, or thumbnails vs. full-sized. If you hard-code to a static, then you'll have to go in every place that was hard-coded and make some sort of change to use a different set, whereas if you use DI, you just supply a different instance loaded with different resources, and done.
Testability. This is actually covered in the link, but I think it bears pulling out. If you want to run a quick test on something that needs a resource, you have to have that static "thing" and you can't change anything about it. It then becomes very difficult to know if the thing you're actually testing is working or if it just appears to be working based on the current implementation of the "thing."
Resource use: everything about an all-static Class exists from the time the swf loads to the time it unloads. Instances only exist from when you instantiate them until they are garbage collected. This can be especially important with resource files that contain embedded assets.
I think the important thing about Frameworks is to realize how they work. The major ones used in ActionScript work the same way, which is they have a central event dispatcher (event bus) that anything loaded to the framework can get a reference to by declaring an interest in it by asking for it to be injected. Additionally, they watch the stage for an event that says that something has been added (in RL it's ADDED_TO_STAGE, whereas in Mate it's the Flex event CREATION_COMPLETE). Once you understand these principles, you can actually apply them yourself with a very light hand without necessarily needing everything that comes along with a framework.
TL;DR
I usually try to avoid answering questions that weren't asked, but in this case I think it would be helpful to discuss an entirely different approach to this problem. At root, the solution comes down not to injecting an entire resource instance, but instead just injecting the resource that's needed.
I don't know what the OP's code is like, but this solution should be general enough that it would work to pass named BitmapDatas to anything that implements our Interface that is capable of dispatching against whatever IEventDispatcher we set as the eventBus (this could be the stage, a particular DisplayObject, or an EventDispatcher that is created just for the purpose.
Note that this code is strikingly similar to code I have in production ;).
public class ResourceManager {
//this can be loaded dynamically, or you can create subclasses that fill the registry
//with embedded Classes in the constructor
protected var registry:Dictionary = new Dictionary();
protected var _eventBus:IeventDispatcher;
public function registerResource(resourceName:String, resourceClass:Class):void {
var bitmap:BitmapData = new resourceClass as BitmapData;
if (resourceClass) {
registry[resourceName] = bitmap;
} else {
trace('Class didn\'t make a BitmapData');
}
}
public function getResource(resourceName:String):BitmapData {
var resource:BitmapData = registry[resourceName];
if (!resource) trace('there was no resource registered for', resourceName);
}
public function get eventBus():IEventDispatcher {
return _eventBus;
}
public function set eventBus(value:IEventDispatcher):void {
if (value != _eventBus){
if (_eventBus) {
_eventBus.removeEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
_eventBus = value;
if (_eventBus) {
_eventBus.addEventListener(YourCustomEvent.GET_RESOURCE, provideResource);
}
}
}
protected function provideResource(e:YourCustomEvent):void {
var client:IBitmapResourceClient = e.target as IBitmapResourceClient;
if (client) {
client.resource = getResource(e.resourceName);//your custom event has a resourceName property that you populated when you dispatched the event.
}
}
}
Note that I didn't provide the Interface or the custom event or an example implementation of the Interface due to the fact I am on my lunch break, but if anyone needs that to understand the code please post back and I'll fill that in.
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();".
When I add an EVENT.ACTIVATE listener to my project, and then alt-tab away and back to my project it triggers twice.
edit: shaunhusain and I seem to have found the cause of the problem, although without a solution. When running the standalone player version 11+ the event triggers 2x. When running standalone player version <11 or any version in the browser it triggers 1x. So it appears there may be a bug in recent versions of the flash player projector. I'm going to nail down the exact versions and report it to adobe and see what happens. Thanks to anyone who read this and tried to help!!
I want it to fire every time I change focus, I just don't want it to fire twice every time I change focus.
Why is this? Am I doing something wrong? What's the best way to prevent this behavior?
It seems like it would be a common question, but Google turned up nothing.
Code:
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite
{
public function Main():void
{
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
stage.addEventListener(Event.ACTIVATE, test);
}
private function test(e:Event):void
{
trace(e.target);
}
}
}
Actual result:
[object Stage]
[object Stage]
Desired result:
[object Stage]
It doesn't seem to make a difference whether I add the listener to the stage or anything else, the behavior is the same.
The same thing also happens with EVENT.DEACTIVATE. Others such as mouse up work fine.
My goal is to pause a game on EVENT.DEACTIVATE and unpause it on EVENT.ACTIVATE. The problem is that when the event fires twice, it calls the unpause function twice which has unwanted consequences.
ActionScript® 3.0 Reference for the Adobe® Flash® Platform says about this event:
Dispatched when the Flash Player or AIR application gains operating
system focus and becomes active. This event is a broadcast event,
which means that it is dispatched by all EventDispatcher objects with
a listener registered for this event. For more information about
broadcast events, see the DisplayObject class.
For me it looks like you want to prevent its designed behavior? I suppose it was designed to fire every time you change focus, or am I wrong? What do you want to accomplish? However this is an answer, so based on what you wrote - you can do a workaround by just removing a listener after he fired once:
private function test(e:Event):void
{
stage.removeEventListener(Event.ACTIVATE, test);
trace(e.target);
}
But I would recommend you to write something more about why are you using it and what want to accomplish if this is not satisfactory.
I've had the same issue in my AIR Mobile app.
To correct this issue, I've stored the last event name triggered for an Activate / Deactivate event. If it is attempted twice in a row, it just gets skipped with a return;
private static function onAppStateChanged(e:Event):void {
if (_STATE == e.type) {
return;
}
_STATE = e.type;
switch(_STATE) {
case Event.ACTIVATE: whenActivated.dispatch(); break;
case Event.DEACTIVATE: whenDeactivated.dispatch(); break;
}
}
At first, the value of _STATE begins with null, so that should allow it to pass through the first time around.
I bind both Event.ACTIVATE and Event.DEACTIVATE to the same listener, onAppStateChanged in my App's initialization method, like so:
_STAGE.addEventListener(Event.ACTIVATE, onAppStateChanged);
_STAGE.addEventListener(Event.DEACTIVATE, onAppStateChanged);
You can replace the Switch-Statement however you like, I just personally prefer using Robert Penner's AS3Signals (GitHub) to broadcast the resume/suspend signal across the App.