Say I have a method that loads all my assets for a Screen, this method is called in that Screens constructor:
public void load(){
manager.load(pd_bg, Texture.class, textureParams);
}
Now when I exit that Screen, I have e method that unloads all these assets:
public void unLoad(){
manager.unload(pd_bg);
}
Inside my Screen I might use this asset for a Sprite, like so:
Sprite bg = new Sprite(GdxAssetManager.manager.get(GdxAssetManager.pd_bg, Texture.class));
Finally, do I need to dispose of the texture used in this sprite even though I call the unLoad() method? i.e:
public void dispose(){
GdxAssetManager.unLoad();
bg.getTexture.dispose(); //Is this line needed?
}
I am also wondering, if I load all resources when I start the app, should I then unload resources when I exit a Screen? How will they be loaded up next time then (since I only load the on launch)?.
I am using a Sprite as an example, but I guess the answer will be true for any asset.
No, you don't have to (and must not) dispose it when you unload it. In general, the rule of thumb goes: if you create it, you destroy it. So if you create a Texture (by using the new keyword) then you own that texture and are responsible for destroying it (calling its dispose method). In the case of AssetManager, it is the AssetManager who owns the resource and is responsible for destroying it.
To keep track of which resources needs to be created and destroyed, AssetManager uses reference counting. So it is important that you eventually call unload for everytime you call load.
And because you created the AssetManager using the new keyword, you own it and you are responsible for calling its dispose method:
public class MyGame extends ApplicationAdapter {
public AssetManager assetManager;
#Override public void create() {
assetManager = new AssetManager();
...
}
...
#Override public void create() {
assetManager.dispose();
assetManager = null;
...
}
}
Have a look at the documentation: https://github.com/libgdx/libgdx/wiki/Managing-your-assets
Btw, in your code it looks like you are using a static AssetManager. Although not related to your question, be aware that will lead to issues. So I'd advice you to implement a proper object oriented design instead of making things static.
As for your second question, it is unclear what you mean. If you mean when you should call AssetManager#unload, then the answer is whenever the class that called the corresponding AssetManager#load method no longer needs it.
For example, if you have an asset named "image.png" and you call the assetManager.load("image.png", Texture.class) in both your MyGame and MyScreen classes then you should call assetManager.unload("image.png") also in both your MyGame and MyScreen class.
To answer your last two questions:
In your launcher class, you should load every texture you need from all screens.
Then in your screens you aceess the images you need and you dont unload them and you also don't dispose them nor do you dispose the assetmanager.
Then in your launcher class in the
dispose(){}
method you first unload evereything and then call
assetmanager.dispose();
Related
Could someone please help me understand how I can properly dispose a Box2D World and Debug Renderer?
I have a playscreen that has a world and renderer and I would like to dispose of these when I change to another screen as I do not need them anymore. I have included in my playscreen dispose with the following, and called this manually when an event has been triggered to change screen. At the moment by calling these dispose() methods my game is crashing. Must a game have to have a Box2D world and renderer at all times? What would 'EXCEPTION_ACCESS_VIOLATION' mean?
#Override
public void dispose() {
System.out.println("PlayScreen disposed.");
world.dispose();
b2dr.dispose();
...
}
From my experience there are (at least) two situations where you can get an EXCEPTION_ACCESS_VIOLATION in libGDX-box2d:
world.dispose is called during world.step
world.dispose is called from a different thread
I'm dealing with a design issue.
Actually, i have a class GameManager, instantiated and updated by a Screen class. The class GameManager, as its name suggests, holds the game logic (transitions between levels, updates other managers, keeps data as score, money ecc...) and the game state (paused, running, game over, transition).
Developing the mechanism of transition between levels, while the transition phase is running, the game should not being updated, but i can't do that from the GameManager because the stages are updated in the Screen class.
I thought about 2 solutions:
1) I move all the game logic in the screen class, so by doing that, in the render method i can easily stop updating stages if i'm in the transition state.
2) Learn how to use finite-state machines in Libgdx
What could i do? Thank you for your help.
Update
I solved (but not avoided bad design) creating this class:
public class GameStateManager {
public static enum GameState {
RUNNING, PAUSE, GAME_OVER, LEVEL_TRANSITION;
}
private static GameState currentGameState;
public static GameState getCurrentGameState() {
return currentGameState;
}
public static void setCurrentGameState(GameState gameState) {
currentGameState = gameState;
}
}
In this way, in the act method of the Actors i can check if the current state of the game is RUNNING. If not, they don't act.
As much as i understand your situation, what you are trying to do is enabling and disabling stage update from a GameManager Class whose object is instantiated in a Screen. And stage is in Screen instead of GameManager. If i got you right then the easiest solution is create a public static boolean TRANSITION = false in Screen.
And enable/disable this from your game manager class by Screen.TRANSITION = true/false. So that stage.act() or whatever code that you want to get stopped when levels are loading can be haulted. Add this in screen class for eg.
if(!TRANSITION)
{ //code
stage.act();
}
I think you have an invalid relation between your classes. Currently your GameManager is owned by Screen. But I tend to think they should be on the same level in your class design table.
I can propose the following:
Create a new class Coordinator. It will own both Screen and GameManager.
Make simple event handling for your classes, so that Coordinator could subscribe to the events, fired by Screen and GameManager
Now, whenever GameManager thinks game situation changed, it can fire some event. Coordinator will decide what to do - to call Screen or not to. And vice versa.
Also, I think your GameManager now handles too much and should be converted into a module because you are heading straight towards God Object antipattern. And that means the whole class design could be changed.
I am writing educational software that utilizes a single "application" swf, which loads external "topic" swf files (containing library items specific to the topic). Each of these external "topic" swf files also utilizes custom classes that solve calculations specific to the topic (ex. trigonometry class for the trigonometry.swf topic file).
I want the trigonometry class of the trigonometry.swf to be able to reference a custom class method that exists in the main "application" swf. If it helps to know the context, I want the user working on trigonometry to be able to type in the trig function the believe to be correct (sin, cos, or tan) and "check" to see if they are right. The "indicate_right_wrong" method exists in a "grader" custom class of the main "application" swf (so that any changes I make to this class will be updated throughout all topics). So...how do I reference a custom class method of a main swf FROM an externally loaded swf file's own custom class?
I DO have the result working when I import the "grader" custom class into each "topic" swf and reference it directly, but I don't want to have to re-publish each topic swf if I make a change to the "grader" custom class. Thus, I'm trying to have each topic capable of referencing the "grader" custom class when it exists within the main "application" swf.
The error I get when I try using variations of parent or parent.parent are property grader_class not found on flash.display.Stage (for parent) and Cannot access a property or method of a null object reference. (when using parent.parent).
Thank you for any help you can provide.
You can't compile code that calls methods not found in the code being compiled. However, you can make runtime calls by evaluating a method. For example:
stage["myfunction"](args);
However, while you could create some sort of pathing logic to reference your methods, as George Profenza indicated, your success will be much higher (and easier to work with) if you simply pass a function listener to a dispatched event or method call.
For example, let's assume you have a custom CHECK_ANSWER event that fires when the user enters an answer. Your gradeAnswer() function (that exists in your "application.swf") would need to register for that event after the child "trigonometry.swf" was loaded. Subsequently, and the data would be passed through.
This, however, may not be ideal as it can cause the child SWF to not unload from memory properly due to a parent registration to a child object (all registrations must be removed first).
Personally, I'd recommend creating a static class which serves as a directory for your application. Each swf loads this class, and lists their pertinent methods as needed. For example:
package com.atriace {
public class Directory {
public static var methods:Object = {
}
}
}
When the application.swf loads, it populates the methods object with your grading function. Subsequent child swfs also load this static class, and expect to find your grade method pre-populated.
Application.swf
import com.atriace.Directory;
Directory.methods["grade"] = gradeAnswer;
Child.swf
import com.atriace.Directory;
Directory.methods["grade"](answers);
Don't know if the quiet is because this kind of question has been answered many times before on Stack Overflow. Anyways here is my take on it..
I want the user working on trigonometry to be able to type in the trig
function the believe to be correct (sin, cos, or tan) and "check" to
see if they are right.
I'm assuming since they have to type the answer you have an input textbox? Also when they have answered they press a button to "submit" their answer? Assuming I'm on the right lines we can do that this way...
note: answer_txt (string) = answer given in external class by user, input_txt = textfield for user input
In the main class have something like
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.*;
import ExternalClass; //your class file attached to relevant topic swf
public class Main extends MovieClip
{
private var _extClass = new ExternalClass(); //create reference to external Class
public function Main()
{
//Ref 1 means do that function when trigger event received from external class
stage.addChild(_extClass); //gives access to "stage" for ExternalClass.as
_extClass.addEventListener("Check_Answer", indicate_right_wrong); //see Ref 1
}
private function indicate_right_wrong (e:Event)
{
//your answer checking code.
//Access answer_txt variable from external class like example below
//_extClass.answer_txt.text = " ";
}
Now in the external class (Trigonometry.as??) you can set up something like this. Make sure answer_txt exists (public var answer_txt:String;)..
public function Question_1 () : void
{
//your code for question + set submit button
submit_BTN.addEventListener(MouseEvent.CLICK, send_Answer);
}
function send_Answer(e:MouseEvent):void
{
answer_txt = input_txt.text; //set input text as final answer
trace("final answer is..." + answer_txt); //just to test it's there
dispatchEvent (new Event ("Check_Answer")); //Main class is waiting for this event (ref 1)
trace ("event dispatched.." + dispatchEvent); //to confirm it was despatched
}
I know there exist a lot of posts about the Frame metadata tag in ActionScript,
but I still didn't find an answer to my question.
The problem is, I have specified a Frame metadata tag above my Main class header:
package gameUI {
...
[Frame(factoryClass="gameUI.MyPreloader")]
public class Main extends Sprite {
public function Main()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{ ...
I also have a preloader class in the same package (gameUI) called MyPreloader.as
package gameUI
{
// imports..
public class MyPreloader extends MovieClip
{
// private vars ..
public function MyPreloader()
{
trace('preloader START');
...
In my IDE, i don't get any errors or warnings. It compiles without problems.
But when I run it, it just skips over the Frame meta tag and just runs the code of the Main class. (The trace in the constructor of MyPreloader is never printed out).
I'm thinking maybe it has something to do with some arguments specified in the compiler settings. I've tried some couple of things, aditional compiler arguments but it never worked.
Does anyone know why he ignores the Frame metatag?
I'm really frustrated right now..
I'm using Flash Builder 4.6.
Compiling with Flex SDK 4.6.
thanks.
Your Main Class is a Sprite, so it can't have two frames. That may be part of your problem.
However, it might be that you can use a process that's easier to debug to accomplish the ultimate goal. For example, this is one approach. I personally usually just set my default export frame as 10, put a spinner on frame 1 and issue a play().
The only assets that need to be compiled on Frame 1 are in the spinner. It will then pause while the spinner spins and the assets load (because it has to load everything compiled there before it can proceed). Once all the assets have loaded, it will naturally advance to Frame 10. I will have an instance on the timeline at Frame 10 that has an associated getter and setter, so when the setter triggers, I know that loading is complete.
I only check "Export in Frame 10" for assets that absolutely have to be loaded at startup (for example, sounds or visual objects that are never used on the timeline).
The advantage of this approach is that you can get to the real content earlier (because only assets compiled on your default frame have to load before you can show anything), but the disadvantage is that it makes no sense to show % progress, since you have no idea what percent of the movie is compiled on frame 10 and needs to load before it will start.
So, in summary:
Try making the Base Class for your fla a MovieClip
If that doesn't work, consider changing approach
I've got an swf loaded externally to my app with loader component. It is loaded to the Application Domain of my loader. I've got a class in that swf wich I would like to extend and override some functions from it. Is it possible somehow?
Here is some code to explain what I want(of course, it is fully incorrect and wold not work):
public var ClassFromLoadedSwf:Class = ApplicationDomain.currentDomain.getDefinition("path.to.needed.class") as Class;
public class MyClass extends ClassFromLoadedSwf
{
override protected function initMovie() : void
{
//function logic goes here
}
}
Thank you for your answers and sorry for my bad english.
No you can't. Basically you don't understand the meaning of ApplicationDomain. Using a loader and Applicaiton Domain you just merge some code to your SWF in Runtime. Before it reaches the Runtime state, it can't be accessed. So at the Compile time you can't do what you're trying to do now. But you can try to use SWC instead of SWF. You just include it in your Project Library and that's all. You'll be able to access all the classes at compile time. Try reading this Article. It will help you understand the meaning of SWCs.