спрайт анимация в openGL

9

У меня проблемы с реализацией спрайтовой анимации в openGL ES. Я прогуглил это, и единственное, что я получаю, это учебник, реализующий через Canvas.

Я знаю путь, но у меня возникают проблемы при его реализации.

Что мне нужно: спрайт анимация при обнаружении столкновений.

Что я сделал: функция обнаружения столкновений работает правильно.

PS: все работает нормально, но я хочу реализовать анимацию ТОЛЬКО в OPENGL. Холст не будет работать в моем случае.

------------------------ РЕДАКТИРОВАТЬ-----------------------

Теперь у меня есть спрайт-лист, скажем, тот, что ниже, с некоторыми определенными координатами, но откуда начнутся координаты (u, v)? Должен ли я считать свои координаты u, v из (0,0) или из (0,5) и по какому шаблону я должен хранить их в своем списке ..? ----> Слева направо ИЛИ ----> сверху вниз

Нужно ли иметь 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
Анимация спрайта и обнаружение столкновений не имеют ничего общего друг с другом.
API-Beast
Какую анимацию вы хотите? Скелет, спрайт, что-то еще?
GameDev-er
@ GameDev-er У меня есть спрайт-лист.
Сиддхарт-Верма
1
@ Mr.Beast Я знаю, что они не имеют ничего общего друг с другом. Моя цель - добиться спрайтовой анимации после столкновения. До сих пор я могу добиться обнаружения столкновений. Но что касается спрайтовой анимации ... я не могу этого сделать. PS: я новичок в openGL ES и здесь тоже .. так что извините за любые мои комментарии, если таковые имеются.
Сиддхарт-Верма
@ Сид Почему у вас х / у перепутали? :( X - горизонтальная ось. (Я знаю, что это не присуще, но это соглашение, против которого нельзя идти)
doppelgreener

Ответы:

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. Это позволит вам перевести уф-пространство.

уф координаты в диапазоне от (0,0) до (1,1)

Предположим, у вас есть квадратная текстура с 4 кадрами, и вы хотите текстурировать квад. Я буду использовать следующие координаты, чтобы определить кадры в ультрафиолетовом пространстве (выбор за вами)

1-й (0, 0) (0,5, 0,5)

2-й (0,5, 0) (1, 0,5)

3-й (0, 0,5) (0,5, 1)

4-й (0,5, 0,5) (1, 1)

С glTexCoordPointer вы должны отобразить 1-й кадр на своем квадре, затем, когда вы хотите показать 2-й кадр, вы вызываете glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) для 3-го и glTranslatef (0,5, 0,5, 0 ) для 4-го.

Приведенный выше код протестирован и работает очень хорошо, надеюсь, пример достаточно ясен.


РЕДАКТИРОВАТЬ:

в конце функции рисования вы должны сбросить матрицу текстур с этим кодом.

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

хорошо, давайте возьмем 5 строк и 4 столбца в качестве примера. В вашем наборе спрайтов не более 20 спрайтов, поэтому используйте int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);

idx теперь изменяется от 0 до number_of_sprites-1 (может быть <20, если у вас есть, например, 5 строк, 4 столбца, но только 18 спрайтов), изменяя его значение каждые 200 мс. Предполагая, что у вас есть спрайт слева направо и сверху вниз, чем вы можете найти координаты фрейма в ультрафиолетовом пространстве, делая это.

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

Марко Мартинелли
источник
Я использую треугольную полосу здесь. Так будет ли это работать в этом случае?
Сиддхарт-Верма
Еще одна вещь ... каким образом я должен хранить координаты? ----> 1D массив ----> 2D массив? Если 1D, то какие координаты мне следует учитывать в массиве?
Сиддхарт-Верма
@ Сид Да, это одно и то же, вам просто нужно использовать правильные координаты UV-отображения. Попробуйте адаптировать мой фрагмент кода, чем если вам нужна дополнительная помощь опубликовать свой код
Марко Мартинелли
UV-координаты @Sid для glTexCoordPointer должны храниться в одномерном массиве
Марко Мартинелли
1
для 1-й проблемы я не знаю, здесь она работает нормально, для второй вам нужно остановить idx для отката до 0, так что простой трюк это. Объявите переменную int oldIdx;до public FragileSquare()этого в методе draw, сделайте так: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; Кстати, я думаю, что мы идем OT, на исходный вопрос был дан ответ, возможно, вам следует закрыть этот вопрос и открыть новый, если это необходимо.
Марко Мартинелли
1

Мое предложение: создать текстуру, содержащую все ваши кадры анимации (рядом). Измените координаты текстуры в соответствии с рамкой, которую вы хотите отобразить.

кортик
источник
Половина этого была сделана. Но как мне добиться этой части ...... «Измените координаты текстуры в соответствии с кадром, который вы хотите отобразить». PS: я новичок в openGL ES.
Сиддхарт-Верма
1

Вам нужно использовать то, что называется spritesheet .

введите описание изображения здесь

Спрайт-лист - это всего лишь одно изображение со всеми «кадрами», которые показывают позы, которые может принять персонаж. Вы выбираете, какой «кадр» листа спрайта отображать либо на основе времени (как для анимации взрыва), либо на входе игрока (например, лицом влево, вправо или рисованием оружия)

Самый простой способ сделать что-то подобное - это чтобы все связанные спрайты были одинакового размера (одинаковой ширины и высоты), и поэтому получить координату (u) 4-го спрайта слева просто (sprite_width*4.0 / sprite_sheet_width).

Если вы пытаетесь оптимизировать и экономить место, вы можете использовать такой инструмент, как TexturePacker, чтобы упаковать свои спрайты на один лист. TexturePacker также генерирует данные json или xml, которые описывают местоположения xy каждого из загружаемых вами спрайтов.

bobobobo
источник
У меня уже есть спрайт лист. Я знаю метод, его сдвигая координаты. Но мой главный вопрос: «Как этого добиться, openGL ES?» у вас есть псевдокод или Java-код для этого? Алгоритм может работать для меня.
Сиддхарт-Верма
2
Написать Spriteкласс. Внутри Spriteкласса паркуется список (u, v) пар, которые описывают (u, v) координаты каждой "неподвижности" в текстуре. Вам нужно еще 2 переменные для отслеживания времени: один с плавающей запятой для хранения «секунд на кадр» (# секунд потратить на каждый кадр анимации) и другой с плавающей запятой «Clock», который хранит «текущее время» в цикле анимации. Когда вы идете рисовать, вы должны обновить текущее время. При превышении «секунд на кадр» вы переходите к следующему кадру анимации, чтобы анимация продолжалась.
Бобобобо
Итак, список, содержащий пары (u, v), будет двухмерным массивом?
Сиддхарт-Верма
см. отредактированный вопрос, пожалуйста.
Сиддхарт-Верма
1

Вы можете использовать I_COLLIDE с OpenGL.

Сделайте каждую сущность в мире коробкой, затем проверьте, сталкиваются ли каждая из осей коробки с другими сущностями.

При большом количестве объектов для проверки на столкновения вы можете захотеть проверить октре. Вы просто делите мир на сектора, а затем проверяете только столкновения между объектами в тех же секторах.

Также используйте движок Bullet Dynamics, который является движком с открытым исходным кодом для обнаружения столкновений и физики.

Md Mahbubur Rahman
источник
обнаружение столкновений уже достигнуто. Моя цель - создать спрайт-анимацию.
Сиддхарт-Верма