I've come across those articles:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/AssetManager.html
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/loaders/PixmapLoader.html
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/assets/loaders/TextureLoader.html
https://github.com/libgdx/libgdx/wiki/Managing-your-assets
And I still didn't find anything about how to load a Texture into the AssetManager.
In my game I create a Pixmap and wrap it around a Texture. Then I dispose the Pixmap. Then I draw the Texture with SpriteBatch. Every Texture created in my game has been created by a Pixmap, so it's created in runtime. How do I load those Textures into the AssetManager?
The links above and everything I've come across only show how to load Textures from already available files.
From your comment
AssetManager can be helpful to prevent taking up memory twice or more.
You probably don't need to use asset manager to prevent this from happening. Instead you can just add a conditional in your code that checks if the asset is already loaded e.g.
if(myTexture != null){
// not loaded
pmap = new Pixmap(10, 10,Format.RGBA8888);
pmap.setColor(Color.RED);
pmap.fill();
myTexture = new Texture(pmap);
pmap.dispose()
}else{
// already loaded, do nothing (or add to count of times used)
}
If you still want to use asset manager you have a couple of options.
You can save your current texture/pixmap images into actual files an load them normally with the asset manager. (simplest option)
Extend the AssetManager (code) and add your own method to add your assets to the assets objectMap and assetTypes objectMap.
Related
I'm developing a game using libgdx library.
When I load the program for the first time, the textures load perfectly and everything is fine
When I close the application, and load it again (I'm assuming Android is somehow caching it from memory) - the wrong textures get loaded.
If I clear the game from history, and try again, it works perfectly.
--
The way it works currently is as follows - I use a SpriteBatch to draw the actual game. I have seperate SpriteBatches to draw the background and Interface (which are loading just fine). On disposing a level, I dispose the SpriteBatch.
for (Block block : world.getDrawableBlocks(this.width, this.height))
{
spriteBatch.draw(block.getTexture(1f), block.getPosition().x, block.getPosition().y, block.SIZE_X, block.SIZE_Y);
}
--
The textures I load using a cache I wrote myself to prevent the same image being loaded more than once. I clear the cache upon the creation of the application. I then keep a Texture / TextureRegion in the object itself, which is obtained through .getTexture()
And here's my code which I use to load the Textures
public static Texture loadTexture(String path)
{
//Do we have the texture cached?
if (textures.containsKey(path))
{
//return it
return textures.get(path);
}
else
{
//load it from the filesystem
Texture texture = new Texture(Gdx.files.internal(path));
//cache it
textures.put(path, texture);
//return it
return texture;
}
}
I attached a debugger and the textures being loaded DO have the correct path.
In the picture example, the texture being swapped happens to be part of the font, which is nothing which is EVER stored in my cache.
--
So, I'm rather stuck here.
Right now I'm using the naughty solution of killing the process manually on dispose:
#Override
public void onDestroy()
{
super.onDestroy();
this.finish();
android.os.Process.killProcess( android.os.Process.myPid() );
}
This works but is pretty dirty.
When the process fails due to an exception, the bug does not occur.
I'm guessing that somehow the library is caching its own textures which are somehow getting corrupted, but I have no idea how to check, nor how to clear them.
So, any ideas?
You need to Dispose() all Textures you have created, for textures loop through all its value() and dispose it on a separate method then use that method in main game's screen dispose() function.
the switched texture seems is BitmapFont, and if those font textures used in UI, then you might have wrong in UI scene or so, also are you loading with JSON file?
seems to me that when you close the game your last texture is font texture is used, and it fills the texture is used on scene.
"new Texture", TextureAtlas, BitmapFont, etc are automatically reloaded after pause/resume or when the OpenGL context is otherwise lost.
I'm guessing your problem must be on the way you handle the manual reloading.
If you want to make sure that no texture is loaded more than once, use AssetManager instead. No need to do all that manually.
From some time I have started having following problem. I play the level it loads files through AssetManager and it displays images. I finish the level, it unloads the files. When I play again the level, it only displays fort, player, enemies, bullets but it stopped displaying the rest of the images like ground, background, trees etc, instead it shows me white plain color.
However just right now, instead of getting the textures from AssetManager ground = manager.get("environment/fields_ground.png"); I just changed everything into creating new objects like ground = new Texture("environment/fields_ground.png"); and it doesn't produce this error. I guess there is something wrong or missing.
It actually was just white plain, but when I created ground as a new texture instead of using AssetManager then it happened as on the picture. I don't unload player image, arrows, but I do unload fort, but the problem doesn't seem to affect it. I assume that something is wrong happening with the AssetManager or it fails to properly clear the screen and batch new images. But files are loaded fine, otherwise it would throw errors. It initializes images otherwise there would be errors and it displays images properly for the first time.
I had a silly mistake, which I didn't notice, because I have too many classes to look at. The mistake was that I disposed ground, background and other objects. After I finished the level it called method to dispose these things and then I played level again and it loaded something what was disposed. Therefore, it caused this problem.
Problem was:
ground.dispose();
background.dispose();
textureEnvironment.dispose();
Solution:
Remove these lines of code.
I've gone through the nice tutorial that creates a simple libgdx game catching raindrops in a bucket. I want to learn more about using images, so I tried replacing the raindrop with a baby.
When I try loading baby.png, I get the following error:
com.badlogic.gdx.utils.GdxRuntimeException: Texture width and height must be
powers of two: 60x83
How can I load an image of whatever size I want?
before loading the image write..
Texture.setEnforcePotImages(false);
you may do this in create function of application listner this is the easiest way if you don't want to create a texture atlas
A little reading led me to a description of TextureAtlas and TexturePacker, which combine a bunch of small images into one large one. That makes them faster to load and draw. As Vikalp says, you can also just disable the rule about image sizes if you don't care about the performance difference.
Texture.setEnforcePotImages(false);
You can learn more about game atlases in Udacity's HTML5 game class.
To create your own atlas, you can start by using the TexturePacker GUI, but I recommend eventually creating a command-line project to automatically pack your raw images.
I posted an example project that takes the example code from the bucket and raindrop tutorial, and switches to using a TextureAtlas. Now, I load the atlas and then load the images from the atlas.
atlas = new TextureAtlas(Gdx.files.internal("atlas/plank.pack"));
dropImage = atlas.findRegion("images/baby");
bucketImage = atlas.findRegion("images/bucket");
One bug I found is that the images wouldn't load in the HTML project. I found out that you can work around the bug by putting all your images in a subfolder.
I created a new project to hold the TexturePacker and any unit tests that I want to add later. The texture packer looks like this:
package com.github.donkirkby.plank;
import com.badlogic.gdx.tools.imagepacker.TexturePacker2;
public class PlankPacker {
public static void main (String[] args) throws Exception {
TexturePacker2.process(
"raw-assets", // source folder
"../plank-game-android/assets/atlas", // destination
"plank.pack"); // data file
}
}
You could also put the picture (top-left corner) into an 128x128 textures aswell:
Afaik is the using of non-power-of-two textures slower and takes more VRAM. Due the architecture of an GPU and "slow" handling of texture bindings in OpenGL, it's always recommended to put your images which are used at the same time into one big pow-two texture and grab them as regions of this texture to speed up your app.
The using and grabbing of your texture would look like:
Texture texture = Gdx.files.internal("data/yourtexture.png");
TextureRegion region = new TextureRegion(texture, 0, 0, 60, 83);
For drawing something like this:
batch.draw(region, positionX, positionY);
My program packs a series of images and outputs them into an aste.png, and an aste.atlas. My code for packing is as follows:
public void pack(){
System.out.println("Packing should not be ordinarily called! If you did not have explicit intentions of Packing, please check ImageAtlas constructor.");
Settings settings = new Settings();
settings.maxWidth = 512;
settings.maxHeight = 512;
TexturePacker2.process(settings, "E:/Files/Eclipse Projects/StarFighters/StarFighters-android/assets/sprites/" + name,
"E:/Files/Eclipse Projects/StarFighters/StarFighters-android/assets/sprites/", name.substring(0,4));
}
I will not need to pack EVERY time I run the program which is why I can get away with absolute file paths(I'll only pack when I'm running desktop and have added new images), however, I only used absolute file paths because I cannot figure out how to do it otherwise. I am using the android assets folder. (The desktop is linked to the android assets folder) As I am running it from the desktop version, it's trying to goto the desktop path, when I need it to use the assets path, which Gdx.files.internal handles for me. (This problem is not essential to the function of my program)
Once I have packed the images I do as follows:
atlas = new TextureAtlas(Gdx.files.internal("sprites/aste.atlas"));
public Texture getTex(String imgname){
return atlas.findRegion(imgname).getTexture();
}
I pass in "sma_a2" as the imgname when I try and getTex();
my assets/sprites/asteroids directory has the following images:
big_a1.png
big_a2.png
med_a1.png
med_a2.png
sma_a1.png
sma_a2.png
Which were all successfully packed into the aste.png and aste.atlas
My problem is, no matter what fname I pass in the image I receive is the entire aste.png
I also was curious as to why I would use a pack instead of just the images, as I start with images, and then pack them, only to get images again..
Don't call getTexture() on the TextureRegion returned from findRegion.
The whole point of an atlas is that all of the textures you look up in it are in the "same" texture, but at different regions within that texture. This way you can "bind" one large texture in OpenGL (which is somewhat expensive) and then render lots of different pieces out of the texture.
Most of the other APIs in Libgdx that take a Texture should also work with a TextureRegion.
**My solution:**
Using "getTexture" returns the entire image, and texture regions store basically a rectangle which represents the regoin of the packaged image that is the individual image. So, basically drawing TextureRegions isn't much different then drawing Textures, so I just drew the TextureRegion. In my case that involved adding to a superclass, so that it supported Textures, and TextureRegions in subclasses. Subclasses specified whether to use Textures or TextureRegions using a boolean, and different SpriteBatch.draw() methods were called for each.
As for why to use them P.T. posted above as follows:
The whole point of an atlas is that all of the textures you look up in
it are in the "same" texture, but at different regions within that
texture. This way you can "bind" one large texture in OpenGL (which is
somewhat expensive) and then render lots of different pieces out of
the texture.
Most of the other APIs in Libgdx that take a Texture should also work
with a TextureRegion.
So sounds to me like it is more effcient/faster.
I am using libgdx and I am loading all my textures as shown below,
Texture objTexture=new Texture(Gdx.files.internal("imagename"));
This code was inside my ApplicationListener. But, I want to load all my images at the start of my game. I don't want to load them inside of ApplicationListener. I have tried accessing texture object outside the scope of OpenGL and failed. Can anyone suggest me on this?
I think that the soonest you can load those textures (it involves uploading them into the VRAM, so I guess that the Graphics module has to be initialized and all the GL stuff done) is in the create function of the ApplicationListener.
Also, you may consider using the new AssetManager to manage your resources. Or write a simpler asset manager.