спрайт-анімація у openGL


9

У мене виникають проблеми із впровадженням анімації спрайтів у openGL ES. Я переглянув це в Google, і єдине, що я отримую, - це Підручник, що реалізується через Canvas.

Я знаю спосіб, але у мене виникають проблеми в його реалізації.

Що мені потрібно: спрайт-анімація щодо виявлення зіткнень.

Що я зробив: Функція виявлення зіткнення працює належним чином.

PS: Все працює нормально, але я хочу реалізувати анімацію лише в OPENGL. Полотно не працюватиме в моєму випадку.

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

Тепер у мене спрайтовий аркуш, скажімо, той, що внизу, має певні координати, але звідки почнуться координати (u, v)? Чи слід вважати мої координати u, v від (0,0) або від (0,5), і в якому шаблоні я повинен зберігати їх у своєму списку ..? ----> Зліва направо АБО ----> зверху вниз

Чи потрібно мені мати 2D масив у своєму класі sprites? ось образ для кращого розуміння.

Спрайт лист Я припускаю, що у мене спрайтовий спрайт 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 і тут теж .. так що вибачте за будь-які мої коментарі, якщо такі є.
Сіддхарт-Верма

@Sid Чому ви змішали х / у? :( X - горизонтальна вісь (я знаю, що це не властиво, але це
умова,

Відповіді:


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 від (0,0) до (1,1)

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

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 мс. Припускаючи, що у вас спрайт зліва направо і зверху вниз, ніж ви можете знайти координату кадру у просторі 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


Я тут використовую трикутну смужку. Так чи спрацює в цьому випадку?
Сіддхарт-Верма

Ще одне. Яким чином я повинен зберігати координати? ----> 1D масив ----> 2D масив? Якщо 1D, то які всі координати я повинен розглянути в масиві?
Сіддхарт-Верма

@Sid Так, це те саме, вам просто потрібно використовувати правильні координати карти відображення. Спробуйте адаптувати мій фрагмент коду, ніж якщо вам потрібна додаткова довідка про розміщення коду
Marco Martinelli

@Sid УФ-координати для glTexCoordPointer потрібно зберігати в 1D масиві
Marco Martinelli

1
для 1-ї проблеми я не знаю, тут вона працює нормально, для другої вам потрібно зупинити idx, щоб повернутись до 0, тому простий трюк у цьому. Задекларуйте змінну int oldIdx;до public FragileSquare()цього в методі малювання, зробіть це так: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; До речі, я думаю, що ми переходимо до ОТ, на оригінальне запитання було відповідено, можливо, ви повинні закрити цю і, якщо потрібно, відкрити нову.
Марко Мартінеллі,

1

Моя пропозиція: Створіть текстуру, що містить усі ваші кадри анімації (поруч). Змініть координати текстури відповідно до кадру, який потрібно відобразити.


Половина зроблена. Але як я повинен досягти цієї частини ...... "Змініть координати текстури відповідно до кадру, який ви хочете відобразити." PS: Я новачок у OpenGL ES.
Сіддхарт-Верма

1

Потрібно використовувати щось, що називається спрайтом .

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

Стритес-лист - це лише одне зображення з усіма різними "рамками", які показують пози, які може приймати персонаж. Ви вибираєте, який "кадр" аркуша спрайта відображатиметься або на основі часу (як для анімації вибуху), або на вході гравця (наприклад, звернені ліворуч, праворуч або малювання пістолета)

Самий простий спосіб зробити що - щось на зразок цього , щоб все пов'язані з спрайтів бути однакового розміру (такої ж ширини і висоти), і тому отримання (і) координата 4 спрайт зліва просто (sprite_width*4.0 / sprite_sheet_width).

Якщо ви намагаєтеся оптимізувати та бути просторовим, ви можете використовувати такий інструмент, як TexturePacker, щоб упакувати спрайти на один аркуш. TexturePacker також висилає дані json або xml, які описують місця xy кожного з спрайтів, які ви завантажуєте.


У мене вже є спрайт-лист. Я знаю метод, його шляхом зміщення координат. Але моє головне питання: "Як цього досягти? у вас є псевдо-код або код java для цього? Алгоритм може працювати для мене.
Сіддхарт-Верма

2
Напишіть Spriteклас. Всередині Spriteпарку класів список пар (u, v), які описують (u, v) координати кожного "нерухомого" текстури. Вам потрібно ще 2 змінні для відстеження часу: один поплавок для зберігання "секунд на кадр" (# секунди, витрачений на кожен кадр анімації), а інший поплавок під назвою "годинник", який зберігає "поточний час" в циклі анімації. Коли ви переходите до малювання, ви повинні оновити поточний час. При перевищенні "секунд на кадр" ви переходите до наступного кадру анімації, щоб анімація рухалася далі.
бобобобо

Гаразд, значить, список, що містить пар (u, v), буде 2d масивом?
Сіддхарт-Верма

див. відредаговане запитання, будь ласка.
Сіддхарт-Верма

1

Ви можете використовувати I_COLLIDE з OpenGL.

Зробіть кожну сутність у світі коробкою, а потім перевірте, чи не стикається кожна з осей вікна з іншими сутностями.

З великою кількістю юридичних осіб для тестування на зіткнення, можливо, ви захочете перевірити указ. Ви б просто розділити світ на сектори, а потім лише перевірити на зіткнення між об'єктами в тих же секторах.

Також використовуйте двигун динаміки кулі, який є двигуном виявлення та зіткнення з відкритим кодом та фізикою.


виявлення зіткнення вже досягнуто. Моя мета - створити спрайт-анімацію.
Сіддхарт-Верма
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.