Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Earlier, I was facing problems on implementing sprite animation in openGL ES.

Now its being sorted up. But the problem that i am facing now is that some of my frames are being skipped when a bullet(a circle) strikes on it.

What I need : A sprite animation should stop at the last frame without skipping any frame.

What I did : Collision Detection function and working properly.

PS : Everything is working fine but i want to implement the animation in OPENGL ONLY. Canvas won't work in my case.

------------------------ EDIT-----------------------

My sprite sheet. Consider the animation from Left to right and then from top to bottom

Here is an image for a better understanding.

My spritesheet ... Spritesheet

class FragileSquare{

FloatBuffer fVertexBuffer, mTextureBuffer;
ByteBuffer mColorBuff;
ByteBuffer mIndexBuff;
int[] textures = new int[1];
public boolean beingHitFromBall = false;
int numberSprites = 20;
int columnInt = 4;      //number of columns as int
float columnFloat = 4.0f; //number of columns as float
float rowFloat = 5.0f;
int oldIdx;

public FragileSquare() {
    // TODO Auto-generated constructor stub

    float vertices [] = {-1.0f,1.0f,            //byte index 0
                         1.0f, 1.0f,            //byte index 1
                                    //byte index 2
                         -1.0f, -1.0f,
                         1.0f,-1.0f};           //byte index 3


    float textureCoord[] = {
                            0.0f,0.0f,
                            0.25f,0.0f,
                            0.0f,0.20f,
                            0.25f,0.20f         


    };


    byte indices[] = {0, 1, 2,
            1, 2, 3 };

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*2 * 4); // 4 vertices, 2 co-ordinates(x,y) 4 for converting in float
    byteBuffer.order(ByteOrder.nativeOrder());
    fVertexBuffer = byteBuffer.asFloatBuffer();
    fVertexBuffer.put(vertices);
    fVertexBuffer.position(0);

    ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(textureCoord.length * 4);
    byteBuffer2.order(ByteOrder.nativeOrder());
    mTextureBuffer =  byteBuffer2.asFloatBuffer();
    mTextureBuffer.put(textureCoord);
    mTextureBuffer.position(0);

}



public void draw(GL10 gl){


    gl.glFrontFace(GL11.GL_CW);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(1,GL10.GL_FLOAT, 0, fVertexBuffer);

    gl.glEnable(GL10.GL_TEXTURE_2D);
       if(MyRender.flag2==1){ /** Collision has taken place*/
    int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); 
    gl.glMatrixMode(GL10.GL_TEXTURE); 
    gl.glTranslatef((idx%columnInt)/columnFloat, (idx/columnInt)/rowFloat, 0);
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    oldIdx = idx;
    }



    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);



    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); //4
    gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer); //5
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //7

    gl.glFrontFace(GL11.GL_CCW);


    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glMatrixMode(GL10.GL_TEXTURE);
    gl.glLoadIdentity();
    gl.glMatrixMode(GL10.GL_MODELVIEW);

}

public void loadFragileTexture(GL10 gl, Context context, int resource)
{
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);


    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle();
}
share|improve this question
    
Your sprite is 5x4 so float rowFloat = 4.0f; shoudn't be float rowFloat = 5.0f;? Also your textureCoord array is incorrect for that sprite, you should use 0.20f as v coordinate because it's 1.0/5; –  Marco Martinelli Sep 26 '12 at 12:26
    
Sorry Sorry, i forgot to edit that part. But its not working, i've updated the code. –  Sid Sep 26 '12 at 12:31
    
The frames that are being skipped are the firsts? –  Marco Martinelli Sep 26 '12 at 12:34
    
they are being skipped in a random order. i just see the first row and the last row in this case and a few(2 or 3) frames from the left overs. –  Sid Sep 26 '12 at 12:40
    
@MarcoMartinelli Hi, I need your help regarding this.. please have a look at the link. gamedev.stackexchange.com/questions/46049/… –  Sid Dec 22 '12 at 16:01

1 Answer 1

up vote 3 down vote accepted

I think that the problem is that you are getting the time from System.currentTimeMillis(). You don't know when your code will be executed so the initial value of idx is unknown. You should save a timestamp when you detect a collision then replace System.currentTimeMillis() with (System.currentTimeMillis()-timestamp)

Pseudocode:

long timestamp;
...
if(new collision detected){
    timestamp = System.currentTimeMillis();
}

In this way your time will start from the moment you detect the collision and idx will always start from 0


EDIT

copy and paste this code, it's not tested but should work.

class FragileSquare{

FloatBuffer fVertexBuffer, mTextureBuffer;
ByteBuffer mColorBuff;
ByteBuffer mIndexBuff;
int[] textures = new int[1];
public boolean beingHitFromBall = false;
int numberSprites = 20;
int columnInt = 4;      //number of columns as int
float columnFloat = 4.0f; //number of columns as float
float rowFloat = 5.0f;
int oldIdx;

long timestamp = System.currentTimeMillis();
lont time=0;

public FragileSquare() {
    // TODO Auto-generated constructor stub

    float vertices [] = {-1.0f,1.0f,            //byte index 0
                         1.0f, 1.0f,            //byte index 1
                                    //byte index 2
                         -1.0f, -1.0f,
                         1.0f,-1.0f};           //byte index 3


    float textureCoord[] = {
                            0.0f,0.0f,
                            0.25f,0.0f,
                            0.0f,0.20f,
                            0.25f,0.20f         


    };


    byte indices[] = {0, 1, 2,
            1, 2, 3 };

    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4*2 * 4); // 4 vertices, 2 co-ordinates(x,y) 4 for converting in float
    byteBuffer.order(ByteOrder.nativeOrder());
    fVertexBuffer = byteBuffer.asFloatBuffer();
    fVertexBuffer.put(vertices);
    fVertexBuffer.position(0);

    ByteBuffer byteBuffer2 = ByteBuffer.allocateDirect(textureCoord.length * 4);
    byteBuffer2.order(ByteOrder.nativeOrder());
    mTextureBuffer =  byteBuffer2.asFloatBuffer();
    mTextureBuffer.put(textureCoord);
    mTextureBuffer.position(0);

}



public void draw(GL10 gl){
    long delta = System.currentTimeMillis() - timestamp;
    timestamp = System.currentTimeMillis();

    gl.glFrontFace(GL11.GL_CW);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(1,GL10.GL_FLOAT, 0, fVertexBuffer);

    gl.glEnable(GL10.GL_TEXTURE_2D);
    if(MyRender.flag2==1){ /** Collision has taken place*/
        int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)(((time+=delta)%(200*numberSprites))/200); 
        gl.glMatrixMode(GL10.GL_TEXTURE); 
        gl.glTranslatef((idx%columnInt)/columnFloat, (idx/columnInt)/rowFloat, 0);
        gl.glMatrixMode(GL10.GL_MODELVIEW); 
        oldIdx = idx;
    }else{
        time = 0;
    }



    gl.glEnable(GL10.GL_BLEND);
    gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);



    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); //4
    gl.glTexCoordPointer(2, GL10.GL_FLOAT,0, mTextureBuffer); //5
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); //7

    gl.glFrontFace(GL11.GL_CCW);


    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glMatrixMode(GL10.GL_TEXTURE);
    gl.glLoadIdentity();
    gl.glMatrixMode(GL10.GL_MODELVIEW);

}

public void loadFragileTexture(GL10 gl, Context context, int resource)
{
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resource);
    gl.glGenTextures(1, textures, 0);
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);


    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle();
}
share|improve this answer
    
The collision is being detected in the renderer class. So that means i have to include TWO STATIC data members, which i want to avoid. –  Sid Sep 26 '12 at 14:43
    
Ok, I have two solutions. In your renderer class set flag2=System.currentTimeMillis() instead of 1 when there is a collision, 0 otherwise. In the draw function replace if(MyRender.flag2==1) with if(MyRender.flag2>0). MyRender.flag2 is now your timestamp and you are still using one static member. Second idea, in your FragileSquare class add a member long timestamp=System.currentTimeMillis(); and another one int delta; At the beginning of your draw method add delta = System.currentTimeMillis(); timestamp=System.currentTimeMillis(); –  Marco Martinelli Sep 26 '12 at 18:12
    
okay but Still System.currentTimeMillis() is there in... int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); So how should i overcome that? In the SECOND IDEA : they both are the same Marco. Timestamp will be initialized as a class level member. and the same as in draw. SO what difference does it make? Please explain –  Sid Sep 26 '12 at 18:17
    
delta is now the amount of milliseconds between each call to the draw method. In your if(MyRender.flag2==1) replace System.currentTimeMillis() with t+=delta; I forgot to tell you that you need to declare int t; near int delta; If you want to repeat the animation every time there is a collision you need to reset t to 0 when there is not a collision (example, add an else{ t=0; }) –  Marco Martinelli Sep 26 '12 at 18:27
    
Sorry, I was adding another comment because of the characters limit. No in the 1st idea you neet to replace System.currentTimeMillis() with (System.currentTimeMillis()-MyRenderer.flag2) –  Marco Martinelli Sep 26 '12 at 18:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.