animasi sprite dalam openGL

9

Saya menghadapi masalah dalam mengimplementasikan animasi sprite di openGL ES. Saya sudah mencarinya di Google dan satu-satunya hal yang saya dapatkan adalah penerapan Tutorial melalui Canvas.

Saya tahu jalannya tetapi saya mengalami masalah dalam mengimplementasikannya.

Yang saya butuhkan: Animasi sprite pada deteksi tabrakan.

Apa yang saya lakukan: Fungsi Deteksi Tabrakan bekerja dengan benar.

PS: Semuanya berfungsi dengan baik tetapi saya ingin mengimplementasikan animasi di OPENGL ONLY. Kanvas tidak akan berfungsi dalam kasus saya.

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

Saya sekarang memiliki lembar sprite, katakanlah yang di bawah ini memiliki beberapa koordinat tertentu, tetapi dari mana koordinat (u, v) akan dimulai? Haruskah saya mempertimbangkan koordinat u, v dari (0,0) atau dari (0,5) dan di pola mana saya harus menyimpannya dalam daftar saya ..? ----> Dari Kiri ke kanan ATAU ----> dari atas ke bawah

Apakah saya perlu memiliki array 2D di kelas sprite saya? di sini adalah gambar untuk pemahaman yang lebih baik.

Lembar sprite Saya berasumsi bahwa saya memiliki lembar sprite NxN, di mana N = 3,4,5,6, .... dan seterusnya.

.

.

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();
}

}

Siddharth-Verma
sumber
1
Animasi sprite dan deteksi tabrakan tidak ada hubungannya dengan satu sama lain.
API-Beast
Apa jenis animasi yang Anda inginkan? Kerangka, sprite sheet, sesuatu yang lain?
GameDev-er
@ GameDev-er Saya punya sprite sheet.
Siddharth-Verma
1
@ Mr.Beast Saya tahu mereka tidak ada hubungannya satu sama lain. Tujuan saya untuk mencapai animasi sprite setelah tabrakan. Sampai sekarang saya dapat mencapai deteksi tabrakan. Tetapi sejauh menyangkut animasi sprite .. saya tidak dapat melakukannya. PS: Saya seorang pemula untuk openGL ES dan di sini juga .. sangat menyesal atas komentar saya, jika ada.
Siddharth-Verma
@ ID Mengapa Anda memiliki campuran x / y? :( X adalah sumbu horizontal. (Saya tahu itu tidak inheren tapi itu adalah konvensi yang tidak boleh dilawan)
doppelgreener

Jawaban:

6

Ini adalah cuplikan kode yang saya gunakan di aplikasi Android saya.

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

Kuncinya di sini adalah menggunakan glMatrixMode diikuti oleh glTranslatef. Itu akan memungkinkan Anda untuk menerjemahkan ruang uv.

koordinat uv berkisar dari (0,0) hingga (1,1)

Misalkan Anda memiliki tekstur kuadrat dengan 4 bingkai dan Anda ingin tekstur quad. Saya akan menggunakan koordinat berikut untuk menentukan frame dalam ruang uv (pilihan terserah Anda)

1 (0, 0) (0,5, 0,5)

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

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

4 (0,5, 0,5) (1, 1)

Dengan glTexCoordPointer Anda harus memetakan frame 1 pada quad Anda kemudian ketika Anda ingin menunjukkan frame ke-2 Anda memanggil glTranslatef (0,5, 0, 0), glTranslatef (0, 0,5, 0) untuk ke-3 dan glTranslatef (0,5, 0,5, 0 ) untuk tanggal 4.

Kode di atas diuji dan bekerja dengan sangat baik, saya harap contohnya cukup jelas.


EDIT:

pada akhir fungsi draw Anda, Anda harus mereset matriks tekstur Anda dengan kode ini.

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

ok, mari kita ambil 5 baris dan 4 kolom sebagai contoh. Ada maksimal 20 sprite di sprite Anda jadi gunakan int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);

idx sekarang beralih dari 0 ke number_of_sprites-1 (bisa <20 jika Anda memiliki misalnya 5 baris, 4 kolom tetapi hanya 18 sprite) mengubah nilainya setiap 200ms. Dengan asumsi Anda memiliki sprite Anda dari kiri ke kanan dan dari atas ke bawah daripada Anda dapat menemukan koordinat bingkai Anda di ruang uv melakukan hal ini.

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);

ketika Anda melakukan idx% c Anda menemukan indeks kolom Anda, hasilnya selalu antara 0 dan c-1

idx% c adalah bilangan bulat, Anda perlu skala ke nilai antara 0,0 dan 1,0 sehingga Anda membaginya dengan cf, cf adalah pelampung sehingga ada pemeran implisit di sini

idx / c adalah hal yang sama tetapi untuk baris, idx dan c keduanya bilangan bulat sehingga hasilnya masih bilangan bulat, dan itu adalah indeks baris, dibagi dengan rf Anda mendapatkan nilai antara 0,0 dan 1,0

Marco Martinelli
sumber
Saya menggunakan strip segitiga di sini. Jadi apakah ini akan berhasil dalam kasus ini?
Siddharth-Verma
Satu hal lagi .. dengan cara apa saya harus menyimpan koordinat? ----> 1D array ----> 2D array? Jika 1D, lalu apa semua koordinat yang harus saya pertimbangkan dalam array?
Siddharth-Verma
@ Id Ya, itu adalah hal yang sama, Anda hanya perlu menggunakan koordinat pemetaan uv yang tepat. Cobalah untuk menyesuaikan cuplikan kode saya daripada jika Anda memerlukan lebih banyak bantuan memposting kode Anda
Marco Martinelli
@Sid Koordinat UV untuk glTexCoordPointer perlu disimpan dalam array 1D
Marco Martinelli
1
untuk masalah 1 saya tidak tahu, ini berfungsi dengan baik di sini, untuk yang kedua, Anda perlu menghentikan idx untuk kembali ke 0 jadi trik sederhana adalah ini. Nyatakan sebuah variabel int oldIdx;sebelum public FragileSquare()itu dalam metode draw, lakukan ini: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; Ngomong-ngomong saya berpikir bahwa kita akan PL, pertanyaan aslinya dijawab, mungkin Anda harus menutup yang ini dan membuka yang baru jika diperlukan.
Marco Martinelli
1

Saran saya: Buat tekstur yang mengandung semua bingkai animasi Anda (berdampingan). Ubah koordinat tekstur sesuai dengan bingkai yang ingin Anda tampilkan.

Beladau
sumber
Setengah dari itu telah dilakukan. Tetapi bagaimana saya harus mencapai bagian ini ...... "Ubah koordinat tekstur sesuai dengan bingkai yang ingin Anda tampilkan." PS: Saya seorang pemula untuk openGL ES.
Siddharth-Verma
1

Anda perlu menggunakan sesuatu yang disebut spritesheet .

masukkan deskripsi gambar di sini

Spritesheet hanyalah gambar tunggal dengan semua "bingkai" berbeda yang menunjukkan pose yang dapat diambil oleh karakter. Anda memilih "bingkai" lembar sprite mana yang akan ditampilkan berdasarkan waktu (seperti untuk animasi ledakan) atau pada input pemain (seperti menghadap ke kiri, kanan, atau menggambar pistol)

Cara termudah untuk melakukan sesuatu seperti ini adalah memiliki semua sprite terkait menjadi ukuran yang sama (lebar dan tinggi yang sama), sehingga mendapatkan koordinat (u) sprite ke-4 dari kiri adalah adil (sprite_width*4.0 / sprite_sheet_width).

Jika Anda mencoba mengoptimalkan dan menghemat ruang, Anda dapat menggunakan alat seperti TexturePacker untuk mengemas sprite Anda ke dalam satu lembar. TexturePacker juga memancarkan data json atau xml yang menjelaskan lokasi xy dari masing-masing sprite yang Anda muat.

bobobobo
sumber
Saya sudah memiliki lembar sprite. saya tahu metodenya, dengan menggeser koordinatnya. Tetapi pertanyaan utama saya adalah "Bagaimana mencapai ini openGL ES?" apakah Anda memiliki pseudo-code atau kode java untuk ini? Algoritme mungkin bekerja untuk saya.
Siddharth-Verma
2
Menulis sebuah Sprite kelas. Di dalam Spritetaman kelas daftar (u, v) pasangan yang menggambarkan (u, v) koordinat masing-masing "masih" dalam tekstur. Anda memerlukan 2 variabel lagi untuk melacak waktu: satu float untuk menyimpan "detik per frame" (# detik untuk dihabiskan pada setiap frame animasi), dan float lain yang disebut "jam", yang menyimpan "waktu saat ini" dalam siklus animasi. Saat Anda menggambar, Anda harus memperbarui waktu saat ini. Ketika "detik per bingkai" terlampaui, Anda pindah ke bingkai animasi berikutnya, sehingga animasi bergerak.
bobobobo
Oke, jadi daftar yang berisi (u, v) pasangan akan menjadi array 2d?
Siddharth-Verma
silakan lihat pertanyaan yang diedit.
Siddharth-Verma
1

Anda dapat menggunakan I_COLLIDE dengan OpenGL.

Buat setiap entitas di dunia kotak, lalu periksa apakah masing-masing sumbu kotak bertabrakan dengan entitas lain.

Dengan sejumlah besar entitas untuk menguji tabrakan, Anda mungkin ingin memeriksa ke sebuah octree. Anda akan membagi dunia menjadi beberapa sektor, kemudian hanya memeriksa tabrakan antar objek di sektor yang sama.

Juga menggunakan mesin Bullet dynamics yang merupakan pendeteksi tabrakan sumber terbuka dan mesin fisika.

Md Mahbubur Rahman
sumber
deteksi tabrakan telah dicapai. Tujuan saya adalah membuat animasi sprite.
Siddharth-Verma