2

由于性能原因,我从 OpenGL ES 2Dcanvas.drawBitmap

这是 4x1 的精灵表:

在此处输入图像描述

现在为了让它工作,我已经上课了:

public Vulcan(ScreenObjectsView objectsView, int vulkanSpriteID, Context context) {     

    this.b = BitmapFactory.decodeResource(context.getResources(), vulkanSpriteID);

    // 1x4
    height = b.getHeight();
    width = b.getWidth()/4;

    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    x = display.getWidth()/2-width/2;  // deprecated
    y = display.getHeight()-height;  // deprecated  

}

public void update() {
    frameFreq++;

    if(frameFreq > 0){
        currentFrame = ++currentFrame % 4;
        frameFreq = 0;
    }       
}


@Override
public void draw(Canvas canvas) {
    update();

    int srcX = currentFrame * width;

    Rect  src = new Rect(srcX, 0, srcX+width, height);
    Rect  dst = new Rect(x, y, x+width, y+height);

    canvas.drawBitmap(b, src, dst, null);
}   

Rect我从左向右移动的每个时间段(循环中):

currentFrame = ++currentFrame % 4;

到目前为止,一切都很好。

如何在 OpenGL ES 中为上述精灵表设置动画?

今天,我知道了如何在 OpenGL ES 中绘制和移动对象(感谢好的演示

但不知道玩精灵。

任何想法,链接,代码片段?

[编辑]

无需使用精灵表或 4 个图像,例如:

在此处输入图像描述在此处输入图像描述等等。

奇怪的是仍然没有得到任何答案或方向。

谢谢,

[编辑 2]

根据 Aert 所说,我实现了以下代码并且它可以工作。

但是看起来很乱

OpenGL ES 的代码太多。对于每个纹理(我有 4 个),我需要创建 FloatBuffer:

也许有人有更短的路,或者我做错了什么。

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;

public class DevQuestSpriteBase {

private static final String LOG_TAG = "Fess";//DevQuestSpriteBase.class.getSimpleName();

protected int mFrame = 0;
protected int mSwitcher = 0;
private int textureCount = 1; // frame animation
protected int[] textures = new int[textureCount]; // frame animation

// texture and verts
protected FloatBuffer vertexBuffer,
textureBuffer1,
textureBuffer2,
textureBuffer3,
textureBuffer4;

ByteBuffer bb1;

protected float vertices[] = {
        0f,0f,0.0f,
        1f,0f,0.0f,
        0f,1f,0.0f,
        1f,1f,0.0f
};


/** 1 frame */
protected float texture1[] = {          
        0.0f, 1.0f,     
        0.0f, 0.0f,     
        0.25f, 1.0f,    
        0.25f, 0.0f     
};
/** 2 frame */
protected float texture2[] = {          

        0.25f, 1.0f,        
        0.25f, 0.0f,        
        0.5f, 1.0f,     
        0.5f, 0.0f      
};
/** 3 frame */
protected float texture3[] = {          
        0.5f, 1.0f,     
        0.5f, 0.0f,     
        0.75f, 1.0f,    
        0.75f, 0.0f     
};
/** 4 frame */
protected float texture4[] = { 
        0.75f, 1.0f,        
        0.75f, 0.0f,        
        1.0f, 1.0f,     
        1.0f, 0.0f      
};


public DevQuestSpriteBase(){
    // vertices buffer
    bb1 = ByteBuffer.allocateDirect(vertices.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    vertexBuffer = bb1.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture1.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer1 = bb1.asFloatBuffer();
    textureBuffer1.put(texture1);
    textureBuffer1.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture2.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer2 = bb1.asFloatBuffer();
    textureBuffer2.put(texture2);
    textureBuffer2.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture3.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer3 = bb1.asFloatBuffer();
    textureBuffer3.put(texture3);
    textureBuffer3.position(0);

    //#########################################################

    // texture buffer
    bb1 = ByteBuffer.allocateDirect(texture4.length * 4);
    bb1.order(ByteOrder.nativeOrder());
    textureBuffer4 = bb1.asFloatBuffer();
    textureBuffer4.put(texture4);
    textureBuffer4.position(0);
}


private void update() {

    if(mSwitcher == 5){
        mFrame = ++mFrame % 4;
        mSwitcher = 0;
        // Log.e(LOG_TAG, "DevQuestSpriteBase :: " + mFrame);
    }
    else{
        mSwitcher++; 
    }   


}

public void draw(GL10 gl){

    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);


    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    if(mFrame == 0){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
    }
    else  if(mFrame == 1){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer2);
    }
    else  if(mFrame == 2){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer3);
    }
    else  if(mFrame == 3){
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer4);
    }


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

    //Log.e(LOG_TAG, "DevQuestSpriteBase :: draw"); 

    update();

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    //gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer1);
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}


public int[] getTextures() {
    return textures;
}
}
4

1 回答 1

1

无需赘述,您需要执行以下操作(假设您已经使用 4 个顶点绘制精灵):

  • 为每个动画帧定义精灵顶点对应的纹理坐标,例如

    texCoordsFrame1 = [0.0f, 0.0f, 0.25f, 0.0f, 0.0f, 1.0f, 0.25f, 1.0f];
    
  • 上传 spritesheet 纹理,例如

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
    
  • 使用与您想要在需要时显示的帧相对应的纹理坐标进行绘制,例如

    ... 
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoordsFrame1);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    

或者,您可以将单独的帧作为单独的纹理上传,但从性能的角度来看这是不可取的。

有几个问题

  • 使用 GLES1 时,您只能使用二次幂纹理。在这种情况下,您必须缩放纹理或将其大小增加到二次方并调整纹理坐标。
  • 位图与 GL 的 y 坐标方向差异有点令人困惑,您最终可能会得到一个垂直翻转的精灵。
于 2013-07-17T03:02:28.377 回答