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.
Related
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'm developping a game which implements gif sprites...
After start with gif I used png image and for change the TextureRegion of my sprite I followed this guide: Sprite.setImage() in andengine and it worked very well.
Now I want to do the same thing with AnimatedSprite. Can someone tell me How i can edit the org.anddev.andengine.entity.sprite.AnimatedSprite.java to create:
sprite.setAnimatedTextureRegion(PixelPerfectTiledTextureRegion textureRegion)
P.S I use also PixelPerfect
The AnimatedSprite class uses the same texture region declared in BaseSprite, so the code in the link you gave will work - just paste it in the AnimatedSprite.java file:
public void setTiledTextureRegion(TiledTextureRegion textureRegion) {
this.mTextureRegion = textureRegion;
}
Note: If the different tiled textures have different number of tiles (So each has a different animation parameters associated with it) you should handle it in your code. It may get complicated, so I'd just create a new AnimatedSprite instead of replacing the texture region.
I am developing a game where I display different sprites on a scene on touch. Each scene has a set of (about 10 sprites) that gets displayed and removed based on user actions. When user navigates to next scenes, I load the sprites for that scene and remove the sprites for the first scene from the cache. I notice a small memory leak on scene change and pin pointed to TiledTextureRegion variables created on 1s scene.
I tried sprite.reset() call but that did not help. I am removing sprites from the scene. This is how the remove sprite code looks like:
private void removeSprite(final AnimatedSprite sprite) {
final PhysicsConnector facePhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(sprite);
this.mPhysicsWorld.unregisterPhysicsConnector(facePhysicsConnector);
this.mPhysicsWorld.destroyBody(facePhysicsConnector.getBody());
this.mScene.unregisterTouchArea(sprite);
this.mScene.detachChild(sprite);
System.gc();
}
But looks like its not clearing TiledTextureRegion objected associated with sprite. Since, I will have lot of different scenes in the app, I am worried memory leak would add up and cause issues.
Any ideas or suggestions will be highly appreciated.
Thanks!!
You can't clear TiledTextureRegion but you can clear BitmapTextureAtlas using BitmapTextureAtlas.unload();.
For example:
BitmapTextureAtlas Texture1 = new BitmapTextureAtlas(null, 1024, 1024, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
mEngine.getTextureManager().loadTexture(Texture7);
ITextureRegion example = BitmapTextureAtlasTextureRegionFactory.createFromAsset(Texture1, this, "picture.png", 0, 0);
And then, when you need:
Texture1.unload();
But probable you don't need to clear memory, because you will use your TiledTextureRegion again. You will recreate your TiledTextureRegion and it will slowdown your application.
I have an AnimatedSprite that after it finishes the animation I want to reverse animate it. I want to do that continuously. Once the reverse animation is complete I want to play the original one. This may be easy one but I am new to Android and AndEngine.
mFlower1Sprite = new AnimatedSprite(20, 800, this.mFlower1);
mFlower1Sprite.setScale((float) 1.5);
mFlower1Sprite.animate(500, 0, new IAnimationListener () {
public void onAnimationEnd(final AnimatedSprite pAnimatedSprite) {
// reverse animation
}
});
mScene.attachChild(mFlower1Sprite);
return mScene;
Use animate method:
public AnimatedSprite animate (long[] pFrameDurations, int[] pFrames,
int pLoopCount, AnimatedSprite.IAnimationListener pAnimationListener)
Animate specifics frames.
Parameters:
pFrameDurations must have the same length as pFrames.
pFrames indices of the frames to animate.
Simply list the indices in reverse order.
I'm working with sprites myself atm and I came across this jQuery plugin. Check it out.
http://spritely.net/
I'm not aware of any support to reverse the frames of an AnimatedSprite, although it's probably a useful feature so I'd love to find out if I'm wrong.
Your best bet would probably be to create another sprite sheet with the frames reversed and another instance of an AnimatedSprite for that sheet. Then define one or two private IAnimationListeners inside your activity (rather than on the fly when you call .animate()), which alternately detach and attach the two sprites at the end of each animation.
I am trying to batch draw a bunch of lines on Android using OpenGL ES 2.0 and I need to know the best way to do this.
Right now I made a class called LineEngine which builds up a FloatBuffer of all the vertices to draw and then draws all the lines at once. The problem is that apparently FloatBuffer.put() is very slow and is gobbling up CPU time like crazy.
Here is my class
public class LineEngine {
private static final float[] IDENTIY = new float[16];
private FloatBuffer mLinePoints;
private FloatBuffer mLineColors;
private int mCount;
public LineEngine(int maxLines) {
Matrix.setIdentityM(IDENTIY, 0);
ByteBuffer byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4);
byteBuf.order(ByteOrder.nativeOrder());
mLinePoints = byteBuf.asFloatBuffer();
byteBuf = ByteBuffer.allocateDirect(maxLines * 2 * 4 * 4);
byteBuf.order(ByteOrder.nativeOrder());
mLineColors = byteBuf.asFloatBuffer();
reset();
}
public void addLine(float[] position, float[] color){
mLinePoints.put(position, 0, 8); //These lines
mLineColors.put(color, 0, 4); // are taking
mLineColors.put(color, 0, 4); // the longest!
mCount++;
}
public void reset(){
mLinePoints.position(0);
mLineColors.position(0);
mCount = 0;
}
public void draw(){
mLinePoints.position(0);
mLineColors.position(0);
GraphicsEngine.setMMatrix(IDENTIY);
GraphicsEngine.setColors(mLineColors);
GraphicsEngine.setVertices4d(mLinePoints);
GraphicsEngine.disableTexture();
GLES20.glDrawArrays(GLES20.GL_LINES, 0, mCount * 2);
GraphicsEngine.disableColors();
reset();
}
}
Is there a better way to batch all these lines together?
What you are trying to do is called SpriteBatching. If you want your program to be robust in openGL es you have to check the following( a list of what makes your program slow ) :
-Changing to many opengl ES states each frame.
-Enable//Dissable (textures etc) again and again. Once you enable something you dont have to do it again it will be applied automaticly its frame.
-Using to many assets instead of spriteSheets. Yes thats make a huge performance impact. For example if you have 10 images you have to load for each image a different texture and that is SLOW. A better way to do this is to create a spriteSheet.(You can check google for free spriteSheet creators).
-Your images are high quality. Yes! check your resolution and file extension. Prefer .png files.
-Care for the api 8 float buffer bug(you have to use int buffer instead to fix the bug).
-Using java containers. This is the biggest pitfall, if you use string concatenation(that's not a container but it returns a new string each time) or a List or any other container that RETURNS A NEW CLASS INSTANCE chances are your program will be slow due to garbage collection. For input handling i would suggest you to search a teqnique called the Pool Class. Its use is to recycle objects instead of creating new ones. Garbage collector is the big enemy, try to make him happy and avoid any programming technique that might call him.
-Never load things on the fly, instead make a loader class and load all the necessary assets in the begining of the app.
If you do implement this list then your chances are your program will be robust.
One last adition. What is a sprite batcher? A spriteBatcher is a class that uses a single texture to render multiple objects. It will create automaticly vertices, indices, colors, u - v coords and it will render them as a batch. This pattern will save GPU power as well as cpu power. From your posted code i can't be sure what causes the cpu to slow down but from my experience is due to one(or more) things of the list i previously mention. Check the list, follow it, search google for spriteBatching and i am sure your program will run fast. Hope i helped!
Edit: I think i found what causes your program to slow down, you dont flip the buffer dude! You just reset the position. You just add add add more objects and you cause buffer overload. In the reset method just flip the buffer. mLineColors.flip mLinePaints.flip will do the job. Make sure you call them each frame if you send new verices each frame.
FloatBuffer.put(float[]) with a relatively large float array should be considerably faster. The single put(float) calls have plenty of overhead.
Just go for a very simple native function which will be called from your class. You can put float[] to OpenGL directly, no need to kill CPU time with a silly buffer interface.