I have to work with big textures in my project so I can't put all the textures into the one BitmapTextureAtlas. I tried to put them into two atlases:
textureAtlas = new BitmapTextureAtlas(2048, 2048, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
textureAtlas2 = new BitmapTextureAtlas(1024, 2048, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
foo = BitmapTextureAtlasTextureRegionFactory.createFromAsset(textureAtlas ,this,"foo.png",0,0);
bar = BitmapTextureAtlasTextureRegionFactory.createFromAsset(textureAtlas2,this,"bar.png",0,0);
But when I try to use bar
Sprite sBar = new Sprite(0,0,bar);
scene.attachChild(sBar);
the only thing I can see is the white rectangle instead of my image. And I have no idea what is wrong here.
OK, I got it. I just forgot about this:
getEngine().getTextureManager().loadTexture(textureAtlas2);
Related
I have three TextureRegions that are created like this:
mBackgroundTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mMenuTextureAtlas, pActivity, "menu_background.png", 0, 0);
mPlayBtnTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mMenuTextureAtlas, pActivity, "play_btn.png", 50, 100);
mExitBtnTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mMenuTextureAtlas, pActivity, "exit_btn.png", 50, 200);
I also have corresponding sprites for each TextureRegion which are created like this:
mBackgroundSprite = new Sprite(0, 0, mBackgroundTextureRegion, mBufferObjectManager);
mPlayBtnSprite = new Sprite(0, 0, mPlayBtnTextureRegion, mBufferObjectManager);
mExitBtnSprite = new Sprite(0, 0, mExitBtnTextureRegion, mBufferObjectManager);
When I attach mBackgroundSprite to a scene like this:
mScene.attachChild(mBackgroundSprite);
I would expect only mBackgroundTextureRegion to appear on the scene (i.e. "menu_background.png") but in reality all three TextureRegions appear (i.e. mPlayBtnTextureRegion and mExitBtnTextureRegion appear too in their location as well, (50,100) and (50,200) respectively).
My questions are:
A. Why does this happen? (does it have something to do with using the same Texture for all TextureRegions?)
B. What is the correct way to make only one TextureRegion appear on a scene?
No this has nothing to do with the texture atlas. This is the correct way of doing it more or less. Nothing should be shown on the screen unless they are attached as a child to something (scene or engine). If you need more straightforward help please upload the part of your code that you are loading the sprite.
I have a backround for message item, I want to make it stretched depending on the text. But when i make this:
Drawable drawableButtonMessageUp = new TextureRegionDrawable(new TextureRegion(new Texture("data/message_my_g.9.png")));
ButtonStyle buttonStyleMessage = new ButtonStyle();
buttonStyleMessage.up = drawableButtonMessageUp;
Button buttonMessage = new Button(buttonStyleMessage);
Label labelMessage = new Label("", new LabelStyle(game.fonts[0], new Color(0, 0, 0, 1)));
buttonMessage.add(labelMessage);
Background does not NinePath, it strached like a normal picture:
My result:
I want (example):
Backround for item:
I checked the nine patch picture in Android SDK, and this work good, how i can do this in libGDX?
It's because you're not using a NinePatch, you're using a TextureRegion
you probably are going to want to change the line
Drawable drawableButtonMessageUp = new TextureRegionDrawable(new TextureRegion(new Texture("data/message_my_g.9.png")));
to something like
Drawable drawableButtonMessageUp = new NinePatchDrawable(new NinePatch(new Texture("data/message_my_g.9.png"), 1, 1, 1, 1));
Note that the number "1" here is a placeholder. You may need to play around with those numbers to get the ninepatch to look right.
For more information, please take a look at the documentation, particularly the section on instantiating ninepatches
I noticed that I can keep one atlas for one textureRegion although I can draw same region multiple times as a sprite. Is it possible to keep all textureRegions in one textureAtlas in a scene?
My special case is, I am generating images instead of using any image file. I do this with BaseBitmapTextureAtlasSourceDecorator and generate the region from IBitmapTextureAtlasSource.
Yes. Generally, though, you should only create atlases with a a max width/height of 1024 (these sizes must be powers of 2, by the way), to be efficient.
On another note, I've found it easier to use BuildableBitmapTextureAtlas. With this kind of atlas, you don't have to specify where in the atlas you are placing your textures. I think it also might take care of sprite-bleeding to some degree (not sure, though). It's the same idea really... Here is an example from my project:
BuildableBitmapTextureAtlas buttonAtlas = new BuildableBitmapTextureAtlas(getTextureManager(), 512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
model.moveLeftButtonTR = BitmapTextureAtlasTextureRegionFactory.createFromAsset(buttonAtlas, this, "moveleft_button.png");
model.moveRightButtonTR = BitmapTextureAtlasTextureRegionFactory.createFromAsset(buttonAtlas, this, "moveright_button.png");
model.handleBlockButtonTR = BitmapTextureAtlasTextureRegionFactory.createFromAsset(buttonAtlas, this, "handleblock_button.png");
model.restartButtonTR = BitmapTextureAtlasTextureRegionFactory.createFromAsset(buttonAtlas, this, "restart_button.png");
try{ buttonAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 1, 1)); }
catch(Exception e){ e.printStackTrace(); }
buttonAtlas.load();
In your case, use the following method:
BitmapTextureAtlasTextureRegionFactory.createFromSource(BuildableBitmapTextureAtlas atlas, IBitmapTextureAtlasSource source)
In summary, the atlas just holds all the textures you add to it. Then you load this atlas into memory so that these textures can be retrieved quickly. You can then use a single instance of a texture to build as many independent sprites as you wish.
I am facing 2 problems.
Questions are listed in picture above.
And main code snippets like this:
My device has a 1024x600 resolution.
Engine:
this.mCamera = new Camera(0, 0,*device'width*,*device'height*);
final EngineOptions engineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED, new FillResolutionPolicy(), this.mCamera);
engineOptions.getTouchOptions().setNeedsMultiTouch(true);
Background:
BitmapTextureAtlas bta = new BitmapTextureAtlas(mGame.getTextureManager(),WIDTH_SCENE_PNG,HEIGHT_SCENE_PNG, TextureOptions.BILINEAR);
ITextureRegion it = BitmapTextureAtlasTextureRegionFactory.createFromResource(bta, mGame, R.drawable.bg_main, 0, 0);
bta.load();
final Sprite sprite = new Sprite(0, 0,*device'width*,*device'height*,it, mGame.getVertexBufferObjectManager());
SpriteBackground bg = new SpriteBackground(sprite);
bg.setColor(Color.PINK);
setBackground(bg);
Sprites:
BitmapTextureAtlas btaTools = new BitmapTextureAtlas(mGame.getTextureManager(), 30, 40);
ITextureRegion itDelete = BitmapTextureAtlasTextureRegionFactory.createFromResource(btaTools, c, R.drawable.sprite_delete,0,0);
btaTools.load();
The distortions could come from the TextureOptions. For the TextureAtlas of your background sprite you use the TextureOptions.BILINEAR. The TextureAtlas of your tools however don't use any options. I guess they have transparent areas? When you use transparent sprites try TextureOptions.NEAREST_PREMULTIPLYALPHA or TextureOptions.BLINEAR_PREMULTIPLYALPHA. I for one use TextureOptions.NEAREST and it works fine for me (even with transparency). Try out some of the options maybe the distortions go away.
The size of your background: for the TextureAtlas bta you already use those constants WIDTH_SCENE_PNG and HEIGHT_SCENE_PNG, why don't you use them for the size of you sprite as well? Anyway, my guess is, that your camera has a different size. For a fullscreen image try:
final Sprite sprite = new Sprite(0, 0,mEngine.getCamera().getWidth(),mEngine.getCamera().getHeight(),it, mGame.getVertexBufferObjectManager());
Christoph
I fixed my problem.
The point is that I moved my resources(png images) from project's drawable-hdpi folder to drawable foler, sprites look nice then.
raw or asset folders are also OK.
Your answer is also helpful for me.Thank you! #Christoph
I want to do an "chain" or circular loop of animations as can be described below:
LABEL start
do Anim1->Anim2->Anim3->Anim4
GOTO start
The above will do a circular loop: Anim1->Anim2->Anim3->Anim4 and back to Anim1 and so on.
I am not able to merge all the PNGs in one Texture because Andengine/Android is limited in loading the resources. However, when I split my initial large tile into 4 smaller tiles, everything works fine.
I tried to use an AnimationListener inside Anim1. When onAnimationFinished() is called, I detach Anim1, and run Anim2 and do this in chain of inner functions. However, when I am in Anim4, I do not know how to go back to the start and attach Anim1.
Note: All this problem could be solved if you know how I can pack a set of 150 PNGs that individually quite large but fit in a tile of 4096x4096 px.
Thank you for your help!
EDIT (following JiMMaR's proposed solution):
I am using Texture Packer and the overall Texture exceeds 4096*4096, causing an OutOfMemory error on Android.
At the moment, I have split the Textures into four tiles and I four PNG tilemaps.
You can use 'Texture Packer' to see if all your images can fit in 4096 x 4096.
You can download Texture Packer from here. (NOTE: Texture Packer supports AndEngine data output too)
You can use "BuildableBitmapTextureAtlas" and "BlackPawnTextureAtlasBuilder" classes to pack your PNGs into one texture atlas.
You should post some code so we can see the implementation.
Try to use several AnimatedSprites with animation listeners in each one. This way you can start the animation of the next sprite in the onAnimationFinished() call.
private class AnimationLooperListener implements IAnimationListener{
private AnimatedSprite nextSpriteToAnimate;
public AnimationLooperListener(AnimatedSprite sprite){
nextSpriteToAnimate = sprite;
}
/** other methods are hidden */
public void onAnimationFinished(AnimatedSprite sprite){
sprite.setVisible(false);
nextSpriteToAnimate.setVisible(true);
nextSpriteToAnimate.animate(100, new AnimationLooperListener(sprite);
}
}
AnimatedSprite sprite1 = new AnimatedSprite(0, 0, tiledTextureRegion, vertex);
AnimatedSprite sprite2 = new AnimatedSprite(0, 0, tiledTextureRegion, vertex);
AnimatedSprite sprite2 = new AnimatedSprite(0, 0, tiledTextureRegion, vertex);
AnimationLooperListener listener1 = new AnimationLooperListener(sprite2);
AnimationLooperListener listener2 = new AnimationLooperListener(sprite3);
AnimationLooperListener listener3 = new AnimationLooperListener(sprite1);
sprite1.animate(100, listener1);
sprite2.animate(100, listener2);
sprite3.animate(100, listener3);
This way, you have an animation loop, between several sprites that can be created using several TiledTextureRegions.