Assets in Libgdx - java

This is my way to deal with assets
I have Assets class which has assetsManager and only Strings of files path
public class Assets {
public static AssetManager manager = new AssetManager();
public static final String background = "bg.png";
public static final String menu = "menu/menu.atlas";
public static Texture getTexture(String name) {
return manager.get(name, Texture.class);
}
public static TextureAtlas getTextureAtlas(String name) {
return manager.get(name, TextureAtlas.class);
}
public static void dispose() {
manager.clear();
}
}
In Screen I load Assets
public class MenuScreen implements Screen {
public void show() {
//load assets
Assets.manager.load(Assets.background, Texture.class);
Assets.manager.load(Assets.menu, TextureAtlas.class);
Assets.manager.finishLoading();
}
}
when I use them I do this
Texture background = Assets.getTexture(Assets.background);
I call dispose in Game Class only
public class GameMain extends Game{
#Override
public void dispose() {
super.dispose();
Assets.dispose();
}
}
My question :
Is this a proper way to manage assets or am I doing anything wrong ?
Another question I have a stage (which have actors which use textureRegions)
In PlayScreen to dispose it(with its textures) I call stage.dispose() only
public class PlayScreen implements Screen{
#Override
public void dispose() {
stage.dispose();
}
}
Is this proper or not ?

The usual way you don't make everything static. So remove every static keyword and put the AssetManager in your main class (which extends Game). Add a Getter for the AssetManager to your main class and pass a reference of your main class to every new Screen class you instantiate. So that the Screen (in your example named PlayScreen) can access the main class and it's AssetManager to load the Screen's assets.
Also the AssetManager is meant to be asynchron, so if you call finishLoading() on it it will block the main thread until all assets are loaded. This is not a problem if you have not much to load but if a game gets bigger usually a splash screen is used and assets are loaded asynchronously in the background. See this libgdx wiki link for more information.
Dispose your AssetManager in the main class (like you did).
Dispose the stage AND the Screen's assets too in the Screen's dispose method. Check this link for a list of classes that need to be disposed manually (to prevent memory leaks).
Also see this question for example code.

Related

Different Textures for same Level Data

The code below shows my Assets class which allows me to load the texture once and call it when I need it globally. If you see that my pack is called house1.pack meaning that there will be more than one house with different art styles. I was wondering if I could achieve a design similar to the popular app Clash Royale with my current code and minor tweaks. I want there to load a different .pack file based on player rank when they are in game. The different houses have the same objects with the same png file names and sizes, but they are just drawn differently.
Thanks,
Denfeet
public class Assets implements Disposable, AssetErrorListener {
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
private AssetManager assetManager;
public AssetFonts fonts;
public AssetDoor door;
public AssetPlatform platform;
public AssetPlayer player;
public AssetControls controls;
// singleton
private Assets() {
}
public void init(AssetManager assetManager) {
this.assetManager = assetManager;
assetManager.setErrorListener(this);
assetManager.load("TexturePacker/house1.pack", TextureAtlas.class);
assetManager.finishLoading();
TextureAtlas atlas = assetManager.get("TexturePacker/house1.pack");
//create game resource objects
fonts = new AssetFonts();
door = new AssetDoor(atlas);
platform = new AssetPlatform(atlas);
player = new AssetPlayer(atlas);
controls = new AssetControls(atlas);
}
#Override
public void error(AssetDescriptor asset, Throwable throwable) {
Gdx.app.error(TAG, "Couldn't load asset '" + asset.fileName + "'", (Exception) throwable);
}
public class AssetFonts {
...
}
public class AssetPlayer {
...
}
public class AssetControls {
...
}
public class AssetDoor {
...
}
public class AssetPlatform {
...
}
}
You can load and unload assets at any time. Provided you don't want to use house1.pack anywhere else in your game, you can:
assetManager.unload("TexturePacker/house1.pack")
to dispose of your house1.pack, then do most of what you have in your init() method to again
assetManager.load("TexturePacker/house2.pack", TextureAtlas.class);
assetManager.finishLoading();
//etc
Not sure how you'd structure your code, but the above is the idea. Depending on how many assets you're talking about (loading time), you may need a natural transition point (not necessarily a full loading screen). But if you want to change textures from one house to another on the fly, you'd probably want to load them all at once at the beginning and find a different method to swap them.

LibGDX - How many references counted in AssetManager of my case?

I created an AssetManger Class called AssetsTest.
package com.program.mydemo;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
public class AssetsTest {
public static AssetManager manager = new AssetManager();
public static void load() {
manager.load("bgscreen.png", Texture.class);
manager.load("menu.pack", TextureAtlas.class);
}
public static void unload() {
manager.unload("bgscreen.png");
manager.unload("menu.pack");
}
public static boolean update(){
return manager.update();
}
public static void dispose() {
manager.dispose();
}
}
I also created another Class called MyDemo
public class MyDemo extends Game {
private SpriteBatch batch;
private Sprite spriteStart1, spriteStart2;
private Texture texture1, texture2;
private TextureAtlas atlas1, atlas2;
private TextureRegion startRegion1, startRegion2;
private Camera camera;
private int refCount;
public void create () {
batch=new SpriteBatch();
camera = new OrthographicCamera(500,700);
AssetsTest.load();
AssetsTest.manager.finishLoading();
texture1 = AssetsTest.manager.get("bgscreen.png",Texture.class);
atlas1 = AssetsTest.manager.get("menu.pack", TextureAtlas.class);
startRegion1 = atlas1.findRegion("startbutton");
spriteStart1 = new Sprite(startRegion1);
spriteStart1.setPosition(-210/2,-150);
texture2 = AssetsTest.manager.get("bgscreen.png",Texture.class);
atlas2 = AssetsTest.manager.get("menu.pack", TextureAtlas.class);
startRegion2 = atlas2.findRegion("startbutton");
spriteStart2 = new Sprite(startRegion2);
spriteStart2.setPosition(-210/2,-150);
refCount = AssetsTest.manager.getReferenceCount("bgscreen.png");
System.out.println(refCount);
// AssetsTest.unload();
// AssetsTest.load();
// AssetsTest.manager.finishLoading();
public void render () {
Gdx.gl.glClearColor(0,0,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(texture2, -500/2,-700/2);
spriteStart2.draw(batch);
batch.end();
}
#Override
public void dispose () {
super.dispose();
batch.dispose();
texture1.dispose();
AssetsTest.dispose();
}
}
Then, I created two Texture References (texture1 & texture2) reference to AssetsTest.manager.get(...);
The refCount is 1. Why?
It should be "2" because I have two references (texture1 & texture2).
If I try to call AssetsTest.load(); twice, I will get refCount is 2. Calling twice of AssetsTest.load(); should create two objects and stored in different memory address. Is my concept correct?
Directly from the libgdx documentation:
Assets are reference counted. If two assets A and B both depend on another
asset C, C won't be disposed until A and B have been disposed.
This also means that if you load an asset multiple times, it will actually be shared and only
take up memory once!
you load
texture1 = AssetsTest.manager.get("bgscreen.png",Texture.class);
and then
texture2 = AssetsTest.manager.get("bgscreen.png",Texture.class);
both texture1 and texture2 point to the same texture which is shared and takes memory only once. That's why you get ref count 1.
Update
Yes, texture1 and texture2 point to the same object ("bgscreen") which is shared. So in a sense they are reference variables pointing to the same memory address. Once an item is loaded in the asset manager it could be reused/shared in this way. In your case this means that no new object will be created each time you reference "bgscreen.png". So you will always get ref count 1.
As regards to the the 2nd part of your question. To clarify some things: Assetmanager.load in its way doesn't load any assets. The method just enqueues the assets. Once you call manager.update() or manager.isFinished only then the assets which you've enqueued with the load method will be loaded into memory. So if you call load twice of the same texture then when you call manager.update() you will end up with two references of the same object ("bgscreen.png") which is unnecessary because what you usually want is have only one shared reference of the same object for efficiency.
If this answers your question please don't forget to accept the response.

Java: Accessing resources and the Law Of Demeter

Overview
In my (Android) Java game, I have a class called resources. As the name suggests, this class holds the resources for the game. All of my OpenGL objects (Sprites) are created here
It's looks something like the following (obviously, this is a simplified version compared to that which appears in the real project):
public class Resources {
Hero hero;
Enemy enemy;
MenuButtons mainMenuButtons;
Background background;
Scene mainMenu;
public void createObjects(){
hero = new Hero();
enemy = new Enemy();
mainMenuButtons = new MenuButtons();
background = new Background();
mainMenu = new Scene(this);
}
}
So, within my mainMenu scene, I need access my objects, so we may see something like this:
public class mainMenu implements Scene {
Resources resources;
public mainMenu(Resources resources){
this.resources = resources;
}
#Override
public void render(){
resources.background.draw();
resources.hero.draw();
resources.enemy.draw();
mainMenuButtons.draw();
}
#Override
public void updateLogic(){
resources.hero.move();
resources.enemy.move();
resources.mainMenubuttons.animate();
}
}
Now, the above method is just one way to get access to the objects in resources and their methods. But does this actually break the Law of Demeter? If not, why not? If so, what is the best way to get access to these objects in a way that does not violate the LOD?
Accessors?
One option (which I've ruled out TBH - see below) is placing accessor methods into my resources class. So that I could do something like:
resources.drawBackround();
I have a lot of objects and I need an accessor for each method/variable of each object. Not really practical, it seems like I'm writing a ton of extra code and most importantly, it makes the resources class ridiculously long as it becomes filled with these accessors. Therefore, I'm not going down this road.
Passing in objects into the scene's constructor
Of course, I can also do something like this:
hero = new Hero();
enemy = new Enemy();
mainMenuButtons = new MenuButtons();
background = new Background();
mainMenu = new Scene(hero, enemy, mainMenuButtons, background);
So I can simply do this:
background.draw(); //etc....
This is workable for simple scene's (such as menu systems that don't require a lot of objects) but for the main game, it could quickly become a mess as I'd have to pass references to some 30+ objects into the constructor which doesn't really sound quite right......
So I would really appreciate if someone could point out the best way to proceed and why.
So I would really appreciate if someone could point out the best way to proceed and why.
The best way, in my opinion, is to keep the Resources class, make all objects private to not break the law and write accessors (but not for every object like you already ruled out).
I have a lot of objects and I need an accessor for each method/variable of each object. Not really practical, it seems like I'm writing a ton of extra code and most importantly, it makes the resources class ridiculously long as it becomes filled with these accessors. Therefore, I'm not going down this road.
I assume many objects are of the same class. So you do not have to make an accessor for every object what would really blow up the class.
I a game you normally have a hero, one or more enemies and many sprites.
public class Resources {
private Hero hero;
private Enemy enemy;
private MenuButtons mainMenuButtons;
private Background background;
private Scene mainMenu;
public void createObjects(){
hero = new Hero();
enemy = new Enemy();
mainMenuButtons = new MenuButtons();
background = new Background();
mainMenu = new Scene(this);
}
public Hero getBackground() {
return background;
}
public Hero getHero() {
return hero;
}
public List<Enemy> getEnemies() {
ArrayList<Enemy> list = new ArrayList<Enemy>();
list.add(enemy);
list.add(next_enemy);
return list;
}
public List<Sprite> getSprites() {
ArrayList<Sprite> list = new ArrayList<Sprite>();
list.addAll(enemy.getActiveSprites());
return list;
}
}
Instead of getHero() and getEnemy() you could also make a getActor() method if Hero and Enemy are derived from the same class.
The getSprites() method is just an example how it could look like.
If that solution is not going to work for you, I have another suggestion.
Make the Resources class do some work.
public class ResourceManager {
private Hero hero;
private Enemy enemy;
private MenuButtons mainMenuButtons;
private Background background;
private Scene mainMenu;
public void createObjects(){
hero = new Hero();
enemy = new Enemy();
mainMenuButtons = new MenuButtons();
background = new Background();
mainMenu = new Scene(this);
}
public void render(Scene scene) {
this.background.draw();
if (scene != mainMenu) {
this.hero.draw();
this.enemy.draw();
}
this.mainMenuButtons.draw();
}
public void updateLogic(Scene scene){
this.hero.move();
this.enemy.move();
this.mainMenubuttons.animate();
}
}
The mainMenu then calls logic methods directly in the RescourceManager class.
public class mainMenu implements Scene {
ResourceManager resourceManager;
public mainMenu(ResourceManager resourceManager){
this.resourceManager = resourceManager;
}
#Override
public void render(){
resourceManager.render(this);
}
#Override
public void updateLogic(){
resourceManager.updateLogic(this);
}
}
I hope my suggestions helped you a bit figure out how to continue with your project.
You could use dependency injection and eliminate your Resources class. Then you can call functions on your fields and wouldn't be in violation of the Law of Demeter.
Here is an example using constructor injection:
public class MainMenu implements Scene {
Background background;
Hero hero;
Enemy enemy;
MenuButtons buttons
public mainMenu(Background background, Hero hero, Enemy enemy, MenuButtons buttons){
this.background = background;
this.hero = hero;
this.enemy = enemy;
this.buttons = buttons;
}
#Override
public void render(){
this.background.draw();
this.hero.draw();
this.enemy.draw();
this.mainMenuButtons.draw();
}
#Override
public void updateLogic(){
this.hero.move();
this.enemy.move();
this.mainMenubuttons.animate();
}
}
With dependency injection, you pass instances into constructors and functions instead of "newing" them inside your class. You need to manage your instances somewhere though, and there are plenty of libraries that will do that for you. Dagger is a popular one for Android: http://square.github.io/dagger/
The idea of passing a list isn't a bad first step, but it's not sufficient. Game developers have a (somewhat controversial) concept of a structure called a "scene graph" that helps them keep track of their resources (among other things). https://en.wikipedia.org/?title=Scene_graph
It's a pretty complicated concept, but you're going to need to learn about it sooner or later. There's a lot of good advice on gamedev.stackexchange.com, so I'd suggest you take a peek over there.
Here's a nice YouTube video tutorial on the subject. https://www.youtube.com/watch?v=ktz9AlMSEoA
You could create an Drawer class that handles the drawing of all the objects. Your scene objects simply need to feed the Drawer the objects that I assume are Drawable.
public class Drawer {
public void drawObjects(Drawable... objects) {
for(Drawable drawable : objects) {
drawable.draw();
}
}
}
This is then used by Scene to draw those objects.
public class mainMenu implements Scene {
Resources resources;
Drawer drawer;
...
public void render() {
drawer.drawObjects(resources.background,
resources.hero,
resources.enemy,
resources.mainMenuButtons);
}
...
}
A similar strategy, using an Updater, can applied for the other methods. If your updateLogic() method makes as simple of calls as it looks, you can definitely do the same thing, by making all those objects inherit from an Updateable interface.
public interface Updateable {
void update();
}
Hero's and Enemy's update() methods could simply call their move() methods, while MenuButtons's update() could delegate to animate(), etc.
Obviously, if you like, you can use some sort of collection instead of varargs for the parameter of Drawer's drawObjects(). I just like the nice fluency made possible by the varargs, since you don't have to create the collection.
For other tips for keeping code in line with the Law of Demeter, check out this article: Law of Demeter and How to Work With It
I like the concept of a ResourceManager. But a ResourceManager should be responsilbe for loading Resources, caching and freeing them. Rendering is definitly a Method of a Render Object.
So the Scence - render Method could delegate the rendering to it after instantiating a Renderer and feed it with Drawables as the Renderer does not render Resources but renderable objects.
Say:
class MainMenu implements Scene {
Renderer sceneRenderer = new Renderer();
AnimatedRenderer animatedRenderer = new AnimatedRenderer();
ResourceManager resourceManager = ResourceManager.getInstance();
List<Resource> resources;
List<Drawable> renderedObjects;
GameObjectController gameObjectController;
void initializeScene() {
resources = resourceManager.getResources();
renderedObjects = resourcesAsRenderables();
sceneRenderer.setDrawables(renderedObjects);
}
List<Drawable> resourcesAsRenderables() {
// if resources are not directly renderable, do decoration etc
// and return a List of Drawable
}
#Override
public void render(){
sceneRenderer.render();
}
#Override
public void updateLogic(){
moveGameObjects();
doAnimations();
}
protected void moveGameObjects() {
gameObjectController.moveAllObjects(this, resources);
}
protected void doAnimations() {
animatedRenderer.render(resources);
}
class ResourceManager {
private static ResourceManager instance = null;
List<Resource> resources;
public ResourceManager getInstance() {
if(instance == null) {
instance = new ResourceManager();
instance.loadResources();
}
return instance;
}
private void loadResources() {
resources = new LinkedList<Resource>();
resources.add(new Hero());
....
}
public List<Resource> getResources() {
return resources;
}
}
This clearly separates the logic and responsibilities for the tasks carried out during the scene lifecycle. A resource manager which is responsible for retrieving resources and as they may take long loading times does things like caching or freeing in low memory situations hiding the details from the client. A renderer which is responsible for displaying the objects and a controller which is responsible for moving the objects. The controller itself may implement handlers for keyboard events but that is not something which must be transparent to the scene. The renderer may swap backgrounds in or out or scale or set lighting effects but the scene only calls its render method. The animated renderer is responsible for starting , rendering and stopping animations.
Change this:
public void render(){
resources.background.draw();
resources.hero.draw();
resources.enemy.draw();
mainMenuButtons.draw();
}
#Override
public void updateLogic(){
resources.hero.move();
resources.enemy.move();
resources.mainMenubuttons.animate();
}
With this:
public void render(){
resources.render();
}
#Override
public void updateLogic(){
resources.update();
}
ResourceManager don't have to know what's inside Resources. It may be one enemy or ten, it doesn't care to ResourceManager.
And so in 'Resource' you can do:
public void update(){
hero.update();// Cause hero may, or may not move, he makes the choice
enemy.update();//...
mainMenubuttons.update();//.
}
public void render(){
...
}
More than this! you could change the "Resource" implementation with an interface and you will be programming for interfaces and not for implementations, which is cool! This way you can have a 'Resources' for in-game and another one for menus that will be used in same way: Only changing, at runtime, the concrete Resources you will be in a menu or in game!
Anyway, not always is needed to fill Demeter.
As can be seen your Resources dont need to be recreated, instead they do use some resources that cant be reloaded (probably images).
You should share the images object within a Resource class, and create your objects within a Scene class, on the constructor of the entities you can get the shared resource that is pre-loaded.

AssetManager seems to not be working

I'm trying to load the level image of my libgdx game with an AssetManager, it seemed easy enough from a guide i followed, but i'm having kind of an error..
i'm using this code in a class called Assets.java
package Loader;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
public class Assets {
public static final AssetManager manager = new AssetManager();
public static final String level1 = "level1.png";
public static void load() {
manager.load(level1, Texture.class);
}
public static void dispose() {
manager.dispose();
}
}
and this code in the main class:
#Override
public void create () {
Assets.load();
while(!Assets.manager.update()) {
System.out.println(Assets.manager.getProgress()*100+"%");
}
setScreen(new GameScreen());
}
but it is always showing me a 0.0% and never loads the image
the file image i'm trying to load weights 300 KB, i've tried with small images too, but nothing changes..
EDIT
it immediately goes to the new screen but still prints out 0.0% endlessly never loading the image
Call the .finishLoading(); if you want to finish loading inside of your create. Else you need to call the .update() inside of your gameloop. For more information see this link.
Moreover i wouldn't make the manager static! You cant guarantee that you just have one of that objects therefore it can happen that if you access an asset you haven't load it at that instance of AssetManager. Whenever you access the manager a new Assetmanager is created and the static method is called. So you would always need to load the assets when you access your manager thats not the right behaviour you whish i think. Create it as regular object and have an instance at your main object which you pass to all other subsystems of your game. Also hold a reference inside of the subsystem so you can use it whenever you need it. => A static version shouldn't work.
Create it like this:
public class Assets {
public AssetManager manager = new AssetManager();
public static final String level1 = "level1.png";
public void load() {
manager.load(level1, Texture.class);
}
public void dispose() {
manager.dispose();
}
}
And use it like this:
private Assets assets;
#Override
public void create () {
assets.load();
//or call the assets.finishLoading();
while(!assets.manager.update()) {
System.out.println(assets.manager.getProgress()*100+"%");
}
setScreen(new GameScreen(assets)); //pass it to the gamescreen ctro!
}
Evenmore you can Extend your Assets class by the AssetManager and direct call the .update on the assets object. Assets extends AssetManager
public class Assets extends AssetManager{
public static final String level1 = "level1.png";
public void load() {
this.load(level1, Texture.class);
}
//dispose not needed since you can call Assets.dispose() since the AssetManager is disposeable.
}
while(!Assets.manager.update()) {
System.out.println(Assets.manager.getProgress()*100+"%");
}
According to your codes, it will only prints out when the assetmanager is not 100% loaded. Try remove the condition and it will actually prints from 0 directly to 1 due to loading of only one texture.

How to open an internal frame

i open a new internalframe in this main frame, i have 2 class,
DisplayInternalFrame aDisplay = new DisplayInternalFrame(name, surname);
desktop.add(aDisplay);
aDisplay.setMaximum(true);
aDisplay.show()
i have a desktop pane and its name desktop, this is my main frame, the internal frame is loading when the application runs,
now my 2nd class is internalframe, it has a table, i want to open new internal frame when people push a table item, my table name is errorTable
private void errorTableMouseClicked(java.awt.event.MouseEvent evt) {
errorInternalFrame acceptFrame = new errorInternalFrame();
desktop.add(acceptFrame);
the desktop is on the class 1 so i cant reach desktop cuz now i am on the internalframe event,
basically when people push an item on the table on the internalframe, open a new internal frame, or something like this.
"the desktop is on the class 1 so i cant reach desktop cuz now i am on the internalframe event, "
What you can do is create an interface with a method to addToDesktop
public interface AddableDesktop {
public void addToDesktop();
}
Then in your class with the desktop, implement it
public class Main extends JFrame implements AddableDesktop {
private JDesktopPane desktop;
#Override
public void addToDesktop() {
errorInternalFrame acceptFrame = new errorInternalFrame();
desktop.add(acceptFrame);
acceptFrame.setVisible(true);
}
}
You'll also need to pass the Main instance (which is an instance of AddableDesktop) to the DisplayInternalFrame. Then you can call the addToDesktop method.
public class DisplayInternalFrame extends JInternalFrame {
private AddableDesktop addableDesktop;
public DisplayInternalFrame(String name, String surname, AddableDesktop ad) {
this.addableDesktop = ad;
}
...
private void errorTableMouseClicked(java.awt.event.MouseEvent evt) {
addableDesktop.addToDesktop();
}
}
When you create the DisplayInternalFrame in your Main class, you'll pass the Main instance to the contructor
DisplayInternalFrame aDisplay =
new DisplayInternalFrame(name, surname, Main.this);
This may not be the exact set up you're looking for, but it shows how you provide functionality from one class to the another.

Categories