Android AndEngine Ontouch Animation - android

I am creating an app using AndEngine for the first time. My app is animation-oriented i.e. it has a number of images which on click animate. Most of these animations are frame by frame animations. I am using AndEngine because I require some animations with particle system, gravity and other stuff. Can someone help me with a simple onclick animation code in AndEngine or maybe point me to some good tutorial since all AndEngine tutorials are game tutorials that do not have frame by frame animation. Any help would be appreciated.

Before starting: note that this answer is using the TexturePacker extension for AndEngine.
For my frame by frame animations I am using a program called Texture Packer, which is supported by AndEngine. You actually just drag all your images to there, and it exports 3 files you need to use inside your project. The file are: .xml , .java , .png
By doing that i'm creating a big bitmap (try to stay below or equal to 2048x2048) with all the frames inside of it.
After assuming you have those files created, you need to copy them to your project. the .png and .xml go into the same directory, most likely under assets/gfx/ ... and the .java file should be located in the src directory with the rest of your classes.
Now lets check out some code..
First of all we will need to load all the textures from the files.. we will do that using the following code:
Those are the variables we will use to create our animatable object.
private TexturePack dustTexturePack;
private TexturePackTextureRegionLibrary dustTexturePackLibrary;
public TiledTextureRegion dust;
The following code actually loads the single textures from the bitmap into our variable
try {
dustTexturePack = new TexturePackLoader(activity.getTextureManager(),"gfx/Animations/Dust Animation/").loadFromAsset(activity.getAssets(),"dust_anim.xml");
dustTexturePack.loadTexture();
dustTexturePackLibrary = dustTexturePack.getTexturePackTextureRegionLibrary();
} catch (TexturePackParseException e) {
Debug.e(e);
}
TexturePackerTextureRegion[] obj = new TexturePackerTextureRegion[dustTexturePackLibrary.getIDMapping().size()];
for (int i = 0; i < dustTexturePackLibrary.getIDMapping().size(); i++) {
obj[i] = dustTexturePackLibrary.get(i);
}
dust = new TiledTextureRegion(dustTexturePack.getTexture(), obj);
As you can see, we are using the TiledTextureRegion object. what we've done until now is actually loading the textures, and giving our TiledTextureRegion object all the info needed about the regions of the smaller images located in our big bitmap.
Later on, to use this in any part of our game, we can do the following: (notice that my "dust" variable is located inside a ResourceManager class, and therefore its public - this info is given for the next code)
AnimatedSprite dustAnimTiledSprite = new AnimatedSprite(500, 125, resourcesManager.dust, vbom);
myScene.attachChild(dustAnimTiledSprite);
At last, to animated the object in a specific given time, we just use the simple method animate, just like this :
dustAnimTiledSprite.animate(40, 0);
(In this case, the duration of each frame is 40, and there is 0 loops - will be animated once)
** Not too sure what's the difference between AnimatedSprite to TiledSprite. but this is how I show simple animations in my game.
I hope this is what you were looking for. good luck

This is sprite sheet with 8 frames
Player.sprite.animate(
new long[] { 100, 100 }, 7, 8,
false, new IAnimationListener() {
public void onAnimationStarted(
AnimatedSprite pAnimatedSprite,
int pInitialLoopCount) {
}
public void onAnimationLoopFinished(
AnimatedSprite pAnimatedSprite,
int pRemainingLoopCount,
int pInitialLoopCount) {
}
public void onAnimationFrameChanged(
AnimatedSprite pAnimatedSprite,
int pOldFrameIndex,
int pNewFrameIndex) {
}
public void onAnimationFinished(
AnimatedSprite pAnimatedSprite) {
Player.sprite.animate(
new long[] { 100,
100, 100,
100, 100,
100, 100 },
0, 6, true);
}
});

Related

How to draw simple 3D model using Android Studio, Vuforia and OpenGL

I have a fully functional iOS app, and now I am working on the Android version in Android Studio.
The app is not a 3D-game, it uses the normal listview etc., but in one activity the app uses Augmented Reality.
I have chosen to use Vuforia (to get more devices' than ARCore+ARKit) and bought this simple 3D model.
https://www.turbosquid.com/3d-models/blend-gift/977474
Now I just want to show my own model on my Vuforia Image Marker. Easy! I thought ...
Vuforia uses OpenGL to render their 3D-model. It is a teapot (https://library.vuforia.com/articles/Training/Image-Target-Guide) and it looks like the class it needs to render the teapot looks like this:
public class Teapot extends MeshObject {
private Buffer mVertBuff;
private Buffer mTexCoordBuff;
private Buffer mNormBuff;
private Buffer mIndBuff;
private int indicesNumber = 0;
private int verticesNumber = 0;
public Teapot()
{
setVerts();
setTexCoords();
setNorms();
setIndices();
}
private void setVerts()
{
double[] TEAPOT_VERTS = { 11.222200, 0.110300, 20.030291, 10.302300, ect. }
mVertBuff = fillBuffer(TEAPOT_VERTS);
verticesNumber = TEAPOT_VERTS.length / 3;
}
private void setTexCoords()
{
double[] TEAPOT_TEX_COORDS = { 0.608828, 0.354913, 0.609037, 0.414650, ect. }
mTexCoordBuff = fillBuffer(TEAPOT_TEX_COORDS);
}
private void setNorms()
{
double[] TEAPOT_NORMS = { -0.964496, 0.067011, -0.255454, -0.865037, ect. }
mNormBuff = fillBuffer(TEAPOT_NORMS);
}
private void setIndices()
{
short[] TEAPOT_INDICES = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, ect. }
mIndBuff = fillBuffer(TEAPOT_INDICES);
indicesNumber = TEAPOT_INDICES.length;
}
}
So i thought - aha - if I could just find the Verts, TexCoords, Norms and Indices of my 3D-model. I could paste them here, and then paint my awesome Christmas gift, instead of the teapot.
I have the 3D-model in:
3D Studio Project
Collada
OBJ
Other textures
FBX
And I also have blender (but almost zero blender-skills). After a long time searching I though that if I could convert the model to a j-son file. I could get the right inputs to draw it. But the created j-son file is veeeeery big! And when I paste the numbers I get from the file, the app crashes with: error: code too large - which I of course do not want :-(
So now im am stuck once again... Maybe my gift is to big? Or my way of doing this is totally wrong?
I think that the Android Studios creaters should make 3D-importing and rendering easier - But that doesn't help me now!
It is just a simple 3D present, and I want it where the simple 3D teapot is.

Drawing 200 textures in LibGdx based Android game

When I draw more around 100-200 textures all in the same screen, the device becomes very slow and the app crashes without any exceptions. Could you please let me know any best way to have 100 textures without compromising the performance.
I am using the TextureRegion from TextureAtlas.
MainGame
public void render(SpriteBatch sb) {
// TODO Auto-generated method stub
// System.out.println("BallPoolGame Screen - render");
batch = sb;
sb.setProjectionMatrix(camera.combined);
sb.begin();
sb.draw(BACKGROUND_BALL_POOL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
cellManager.draw(sb);
ballManager.draw(sb);
sb.end();
}
private void setGameTextures() {
gameScreenAtlas = new TextureAtlas("data/texturetutorialpack.pack");
RED_BALL = gameScreenAtlas.findRegion("redball");
// RED_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
BLUE_BALL = gameScreenAtlas.findRegion("blueball");
// BLUE_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
GREEN_BALL = gameScreenAtlas.findRegion("greenball");
// GREEN_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
CellManager
public void draw(SpriteBatch sb){
batch=sb;
showImageTexture(MODEL1,207,1);
if(showSelectedCell){
if(allPossiblePathSize>0)
setupBoardCellTexture();
showImage(CELL_SELECTED, rowCoordinate[cellRow], colCoordinate[cellCol]);
}
}
private void setupBoardCellTexture(){
for(CellGrid c : masterGrid){
if(cellTextureIndicator[c.getRow()][c.getCol()]==1){
showImage(CELL_ALL_PATH_TEXTURE,c.getRowCoordinate() ,c.getColCoordinate() );
}
}
}
private void showImage(TextureRegion tr, float rowCoordinate, float colCoordinate) {
batch.draw(tr, colCoordinate,rowCoordinate);
}
BallManager
public void draw(SpriteBatch sb) {
batch = sb;
setupBoardBallTexture();
if (moveTheBall) {
updateBallPosition();
showImage(ball.getTextureRegion(), moveRow + 6, moveCol + 6);
}
squeezeBalls.draw(sb);
}
You are missing some essential data about your app to answer than question:
How big is one texture on average (Size: widthxheight)
On which device is this error occuring (some devices might have less fillrate than others)
What texture filter does the TextureAtlas use (LINEAR, NEAREST, ...)
I guess that you are trying to draw many textures event if they are out of sight. If that is the case you have to implement a check if the cell is visible to the camera.
Another guess would be that you are trying to draw too many elements with the LINEAR TextureFilter. When using linear as a texture filter the gpu needs to sample way more points then with nearest (i think it was 4 times the samples; so in theory your gpu draws 400-800 textures; depending on images size that are too much for mobile gpu fillrates)
Try to describe more circumstances then i can give probably more insight in your problem.

animate specific sprite with multiple sprite on android using andengine

i have multiple objects on my canvas. and after some condition, i want some of my sprite do animate. here my code:
private AnimatedSprite[] sign;
sign = new AnimatedSprite[9];
// some loop code to create 9 sign
..
sign[index] = new AnimatedSprite(x, y, myregion);
..
until this part is ok, all signs is on position. but when i want to animate some sprite, all of that sprite will do animate too. here the code:
while(signIndex<9)
{
if(signIndex==winSlot[0] || signIndex==winSlot[1] || signIndex==winSlot[2])
{
grupSign= null;
grupSign= sign[signIndex];
grupSign.animate(200, true);
}
signIndex++;
}
anyone know and can help me how to make only specific sprites do animate?
As per my suggestion you have to use deepCopy() method while you create your animated sprite object. As per the following
sign[index] = new AnimatedSprite(x, y, myregion.deepCopy());
Advantage of using deepCopy() method is that each time new region will created for your sprite.

animated sprite from texturepacker xml

new to android dev and andengine in general. trying to animate a sprite using the AndEngineTexturePackerExtension but im unsure how the tiledTextureRegion gets created for the animated sprite. below is what im trying which i have gotten from guides and other posts in this forum. Im creating the xml,png and java from texturepacker
private TexturePackTextureRegionLibrary mSpritesheetTexturePackTextureRegionLibrary;
private TexturePack texturePack;
try
{
TexturePackLoader texturePackLoader = new TexturePackLoader(activity.getTextureManager());
texturePack = texturePackLoader.loadFromAsset(activity.getAssets(), "spritesheet.xml");
texturePack.loadTexture();
mSpritesheetTexturePackTextureRegionLibrary = texturePack.getTexturePackTextureRegionLibrary();
}
catch (TexturePackParseException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
TexturePackerTextureRegion textureRegion = mSpritesheetTexturePackTextureRegionLibrary.
get(spritesheet.00000_ID);
TiledTextureRegion tiledTextureRegion = TiledTextureRegion.create(texturePack.getTexture(),
textureRegion.getSourceX(), textureRegion.getSourceY(),
textureRegion.getSourceWidth() , textureRegion.getSourceHeight() ,
COLUMNS, ROWS);
AnimatedSprite sprite = new AnimatedSprite((activity.CAMERA_WIDTH - tiledTextureRegion.getWidth()) / 2,
(activity.CAMERA_HEIGHT - tiledTextureRegion.getHeight()) / 2,
tiledTextureRegion, activity.getVertexBufferObjectManager());
the problem is that i dont understand where the values from COLUMNS and ROWS comes from? the sprite sheet itself has uneven rows and columns as it includes rotated sprites etc. So im confused as to where these values come from. Any help on getting this working would be great thanks
edit: Ok i can get the sprite sheet animation working if i just use the basic algorithm within texture packer and not the MaxRects algorithm. But this doesnt make use of all the space within a sheet so i would rather get it working using a MaxRects generated sprite sheet. I see with in the xml that it pass a bool for being rotated or not so the information is there to make this work i just cant figure out how. how do i use a texturepackertexture region to make an animated sprite when some of the textures are rotated on the sheet
TexturePacker doesn't know how much columns and rows have your sprites, not even if they are tiled or not, it just packs everything into a single spritesheet (png file for example). Also, its goal isn't to create TiledSprites from separated Sprites.
So, in order to get back a TiledSprite (or AnimatedSprite) from a spritesheet, you have to know how much columns and rows (it can be hardcoded somewhere) it had before being put into the spritesheet, since TexturePacker won't give you that kind of information.
I personally use a TextureRegionFactory which looks like this:
public class TexturesFactory {
public static final String SPRITESHEET_DIR = "gfx/spritesheets/";
public static final String TEXTURES_DIR = SPRITESHEET_DIR+"textures/";
private TexturePack mTexturePack;
private TexturePackTextureRegionLibrary mTextureRegionLibrary;
/**
*
* #param pEngine
* #param pContext
* #param filename
*/
public void loadSpritesheet(Engine pEngine, Context pContext, String filename) {
try {
this.mTexturePack = new TexturePackLoader(
pEngine.getTextureManager(), TEXTURES_DIR).loadFromAsset(
pContext.getAssets(), filename);
this.mTextureRegionLibrary = this.mTexturePack.getTexturePackTextureRegionLibrary();
this.mTexturePack.getTexture().load();
} catch (TexturePackParseException ex) {
Log.e("Factory", ex.getMessage(), ex);
}
}
public TextureRegion getRegion(int id) {
return this.mTextureRegionLibrary.get(id);
}
public TiledTextureRegion getTiled(int id, final int rows, final int columns) {
TexturePackerTextureRegion packedTextureRegion = this.mTextureRegionLibrary.get(id);
return TiledTextureRegion.create(
packedTextureRegion.getTexture(),
(int) packedTextureRegion.getTextureX(),
(int) packedTextureRegion.getTextureY(),
(int) packedTextureRegion.getWidth(),
(int) packedTextureRegion.getHeight(),
columns,
rows);
}
}
Edit: About the rotated problem, it is written inside the xml generated by TexturePacker, so you can get it by calling
TexturePackerTextureRegion packedTextureRegion = this.mTextureRegionLibrary.get(id);
packedTextureRegion.isRotated()
Then, you can create the tiledTextureRegion according to that value with:
TiledTextureRegion.create(
packedTextureRegion.getTexture(),
(int) packedTextureRegion.getTextureX(),
(int) packedTextureRegion.getTextureY(),
(int) packedTextureRegion.getWidth(),
(int) packedTextureRegion.getHeight(),
columns,
rows,
packedTextureRegion.isRotated());
Also, I hope it is clear to you that TexturePacker isn't meant to create tiled sprites. You must create your tiled sprites (nice fit or rows and columns) before using TexturePacker.

How is Animation implemented in Android

I had a small question.If i want to make a man run in android one way of doing this is to get images of the man in different position and display them at different positions.But often,this does not work very well and it appears as two different images are being drawn.Is there any other way through which i can implement custom animation.(Like create a custom image and telling one of the parts of this image to move).
The way i do it is to use sprite sheets for example (Not my graphics!):
You can then use a class like this to handle your animation:
public class AnimSpriteClass {
private Bitmap mAnimation;
private int mXPos;
private int mYPos;
private Rect mSRectangle;
private int mFPS;
private int mNoOfFrames;
private int mCurrentFrame;
private long mFrameTimer;
private int mSpriteHeight;
private int mSpriteWidth;
public AnimSpriteClass() {
mSRectangle = new Rect(0,0,0,0);
mFrameTimer =0;
mCurrentFrame =0;
mXPos = 80;
mYPos = 200;
}
public void Initalise(Bitmap theBitmap, int Height, int Width, int theFPS, int theFrameCount) {
mAnimation = theBitmap;
mSpriteHeight = Height;
mSpriteWidth = Width;
mSRectangle.top = 0;
mSRectangle.bottom = mSpriteHeight;
mSRectangle.left = 0;
mSRectangle.right = mSpriteWidth;
mFPS = 1000 /theFPS;
mNoOfFrames = theFrameCount;
}
public void Update(long GameTime) {
if(GameTime > mFrameTimer + mFPS ) {
mFrameTimer = GameTime;
mCurrentFrame +=1;
if(mCurrentFrame >= mNoOfFrames) {
mCurrentFrame = 0;
}
}
mSRectangle.left = mCurrentFrame * mSpriteWidth;
mSRectangle.right = mSRectangle.left + mSpriteWidth;
}
public void draw(Canvas canvas) {
Rect dest = new Rect(getXPos(), getYPos(), getXPos() + mSpriteWidth,
getYPos() + mSpriteHeight);
canvas.drawBitmap(mAnimation, mSRectangle, dest, null);
}
mAnimation - This is will hold the actual bitmap containing the animation.
mXPos/mYPos - These hold the X and Y screen coordinates for where we want the sprite to be on the screen. These refer to the top left hand corner of the image.
mSRectangle - This is the source rectangle variable and controls which part of the image we are rendering for each frame.
mFPS - This is the number of frames we wish to show per second. 15-20 FPS is enough to fool the human eye into thinking that a still image is moving. However on a mobile platform it’s unlikely you will have enough memory 3 – 10 FPS which is fine for most needs.
mNoOfFrames -This is simply the number of frames in the sprite sheet we are animating.
mCurrentFrame - We need to keep track of the current frame we are rendering so we can move to the next one in order.~
mFrameTimer - This controls how long between frames.
mSpriteHeight/mSpriteWidth -These contain the height and width of an Individual Frame not the entire bitmap and are used to calculate the size of the source rectangle.
Now in order to use this class you have to add a few things to your graphics thread. First declare a new variable of your class and then it can be initialised in the constructor as below.
Animation = new OurAnimatedSpriteClass();
Animation.Initalise(Bitmap.decodeResource(res, R.drawable.stick_man), 62, 39, 20, 20);
In order to pass the value of the bitmap you first have to use the Bitmap Factory class to decode the resource. It decodes a bitmap from your resources folder and allows it to be passed as a variable. The rest of the values depend on your bitmap image.
In order to be able to time the frames correctly you first need to add a Game timer to the game code. You do this by first adding a variable to store the time as show below.
private long mTimer;
We now need this timer to be updated with the correct time every frame so we need to add a line to the run function to do this.
public void run() {
while (mRun) {
Canvas c = null;
mTimer = System.currentTimeMillis(); /////This line updates timer
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
Animation.update(mTimer);
doDraw(c);
}....
then you just have to add Animation.draw(canvas); your Draw function and the animation will draw the current frame in the right place.
When you describe : " one way of doing this is to get images of the man in different position and display them at different positions", this is indeed not only a programming technique to render animation but a general principle that is applied in every form of animation : it applies to making movies, making comics, computer gaming, etc, etc.
Our eyes see at the frequency of 24 images per second. Above 12 frames per second, your brain gets the feeling of real, fluid, movement.
So, yes, this is the way, if you got the feeling movement is not fuild, then you have to increase frame rate. But that works.
Moving only one part of an image is not appropriate for a small sprite representing a man running. Nevertheless, keep this idea in mind for later, when you will be more at ease with animation programming, you will see that this applies to bigger areas that are not entirely drawn at every frame in order to decresase the number of computations needed to "make a frame". Some parts of a whole screen are not "recomputed" every time, this technique is called double buffer and you should soon be introduced to it when making games.
But for now, you should start by making your man run, replacing quickly one picture by another. If movement is not fuild either increase frame rate (optimize your program) or choose images that are closer to each other.
Regards,
Stéphane

Categories

Resources