openGL中的精灵动画


9

我在OpenGL ES中实施精灵动画时遇到问题。我已经用谷歌搜索了,唯一得到的是通过Canvas实现的教程。

我知道方法,但是在实施过程中遇到问题。

我需要的是有关碰撞检测的Sprite动画。

我的工作:碰撞检测功能正常运行。

PS:一切工作正常,但我只想在OPENGL中实现动画。在我的情况下,Canvas无法正常工作。

------------------------编辑-----------------------

我现在有一张Sprite表,说下面的这张表有一些特定的坐标,但是(u,v)坐标从哪里开始?我应该从(0,0)还是从(0,5)考虑我的u,v坐标,并且应该以哪种模式将它们存储在列表中?---->从左到右或---->从上到下

我的sprites类中是否需要2D数组?这是一个更好理解的图像。

雪碧表 我假设我有一个NxN的精灵表,其中N = 3、4、5、6等。

class FragileSquare{

FloatBuffer fVertexBuffer, mTextureBuffer;

ByteBuffer mColorBuff;

ByteBuffer mIndexBuff;

int[] textures = new int[1];

public boolean beingHitFromBall = false;

int numberSprites = 49;

int columnInt = 7;      //number of columns as int

float columnFloat = 7.0f; //number of columns as float

float rowFloat = 7.0f;


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.142f,0.0f,
                            0.0f,0.142f,
                            0.142f,0.142f           


    };


    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);
    int idx = (int) ((System.currentTimeMillis()%(200*4))/200);
    gl.glMatrixMode(GL10.GL_TEXTURE); 
    gl.glTranslatef((idx%columnInt)/columnFloat, (idx/columnInt)/rowFloat, 0);
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    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();
}

}


1
Sprite动画和碰撞检测彼此无关。
API-Beast

您要什么样的动画?骨骼,精灵表,还有其他东西吗?
GameDev-er 2012年

@ GameDev-er我有一张精灵表。
Siddharth-Verma 2012年

1
@野兽先生,我知道他们彼此无关。我的目标是在碰撞后实现精灵动画。到目前为止,我已经能够实现碰撞检测。但是就精灵动画而言..我无法做到。PS:我是openGL ES的新手,也可以在这里..非常抱歉,如果有任何意见。
Siddharth-Verma 2012年

@Sid为什么您将x / y混在一起?:( X是水平轴。(我知道这不是天生的,但这是一个不应该违背的惯例)
doppelgreener 2012年

Answers:


6

这是我在Android应用程序中使用的代码段。

gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glMatrixMode(GL10.GL_TEXTURE);    //edit the texture matrix
gl.glTranslatef(u, v, 0);            //translate the uv space (you can also rotate, scale, ...)
gl.glMatrixMode(GL10.GL_MODELVIEW);  //go back to the modelview matrix
gl.glBindTexture(GL10.GL_TEXTURE_2D, getTexture());
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);           //map the texture on the triangles
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, getTextureBuffer()); //load texture coordinates

这里的技巧是使用glMatrixMode和glTranslatef。这样您就可以翻译uv空间。

uv坐标范围从(0,0)到(1,1)

假设您有一个带有4帧的正方形纹理,并且想要对四边形进行纹理化。我将使用以下坐标在uv空间中定义帧(选择取决于您)

第一(0,0)(0.5,0.5)

第二(0.5,0)(1、0.5)

第三(0,0.5)(0.5,1)

第四(0.5,0.5)(1、1)

使用glTexCoordPointer时,您应该将第一个帧映射到四边形上,然后在要显示第二个帧时,请为第三个调用glTranslatef(0.5,0,0),glTranslatef(0,0.5,0)和glTranslatef(0.5,0.5,0) )。

上面的代码已经过测试并且运行良好,我希望示例足够清楚。


编辑:

在绘图功能的最后,您应该使用此代码重置纹理矩阵。

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

好的,我们以5行4列为例。您的spriteset中最多可以包含20个sprite,因此请使用int idx =(int)(((System.currentTimeMillis()%200 * number_of_sprites)))/ 200);

idx现在从0变为number_of_sprites-1(如果您有5行,4列但只有18个sprite,则可以小于20)每200ms更改一次它的值。假设您的精灵从左到右,从上到下,那么您可以在uv空间中找到帧坐标。

int c = 4;      //number of columns as int
float cf = 4.f; //number of columns as float
float rf = 5.f; //number of rows as float
gl.glTranslatef((idx%c)/cf, (idx/c)/rf, 0);

当您执行idx%c时,您会发现列索引,结果始终在0到c-1之间

idx%c是整数,您需要将其缩放为0.0到1.0之间的值,以便除以cf,cf是浮点数,因此这里有一个隐式转换

idx / c是同一件事,但是对于行,idx和c都是整数,因此结果仍然是整数,它是行索引,除以rf,您将得到一个介于0.0和1.0之间的值


我在这里使用三角带。那么在这种情况下会起作用吗?
Siddharth-Verma 2012年

还有一件事..我应该以什么方式存储坐标?----> 1D阵列----> 2D阵列?如果是1D,那么我应该在数组中考虑所有坐标吗?
Siddharth-Verma 2012年

@Sid是的,是同一回事,您只需要使用正确的uv映射坐标即可。如果您需要更多帮助来发布代码,请尝试修改我的代码片段
Marco Martinelli 2012年

glTexCoordPointer的@Sid UV坐标需要存储在1D数组中
Marco Martinelli

1
对于我不知道的第一个问题,它在这里工作正常,对于第二个问题,您需要停止idx以回滚到0,所以这是一个简单的技巧。声明一个变量int oldIdx;public FragileSquare()然后在draw方法中执行此操作:int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; 顺便说一句,我认为我们即将开始,最初的问题已得到解答,也许您应该关闭此变量,并在需要时打开一个新变量。
Marco Martinelli 2012年

1

我的建议:创建包含动画所有帧的纹理(并排)。根据要显示的帧更改纹理坐标。


已经完成了一半。但是我应该如何实现这一部分……“根据要显示的帧更改纹理坐标。” PS:我是openGL ES的新手。
Siddharth-Verma 2012年

1

您需要使用一种称为spritesheet的东西。

在此处输入图片说明

Spritesheet只是具有所有不同“框架”的单个图像,显示角色可以采取的姿势。您可以根据时间(如爆炸动画)或玩家输入(例如,向左,向右或画枪)选择要显示的Sprite工作表的“帧”

做这样的最简单的方法是使所有相关的子画面具有相同的大小(相同的宽度和高度),因此从左侧获取第4个子画面的(u)坐标为just (sprite_width*4.0 / sprite_sheet_width)

如果您要优化和节省空间,可以使用TexturePacker之类的工具将子画面打包到一张纸上。TexturePacker还发出json或xml数据,这些数据描述了您加载的每个精灵的xy位置。


我已经有了一张精灵表。我知道方法,通过移动坐标。但是我的主要问题是“如何通过openGL ES实现这一目标?” 您有任何伪代码或Java代码吗?该算法可能对我有用。
Siddharth-Verma 2012年

2
写一Sprite堂课。在Sprite类内部停放一列(u,v)对,它们描述纹理中每个“静止”的(u,v)坐标。您还需要2个变量来跟踪时间:一个浮点数用于存储“每帧秒数”(每个动画帧花费#秒),另一个浮点数称为“时钟”,其在动画周期中存储“当前时间”。绘图时,必须更新当前时间。当超过“每帧秒数”时,将移至动画的下一帧,以便动画继续进行。
bobobobo 2012年

好的,所以包含(u,v)对的列表将是一个2d数组?
Siddharth-Verma 2012年

请参阅编辑后的问题。
Siddharth-Verma 2012年

1

您可以将I_COLLIDE与OpenGL 一起使用。

将世界上的每个实体都设为一个框,然后检查该框的每个轴是否与其他实体发生碰撞。

对于要测试碰撞的大量实体,您可能需要检入八叉树。您可以将世界简单地划分为多个扇区,然后仅检查相同扇区中对象之间的碰撞。

还利用Bullet动力学引擎,这是一个开源的碰撞检测和物理引擎。


碰撞检测已经实现。我的目的是创建一个精灵动画。
Siddharth-Verma 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.