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.
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();
}
}
Jawaban:
Ini adalah cuplikan kode yang saya gunakan di aplikasi Android saya.
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.
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.
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
sumber
int oldIdx;
sebelumpublic 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.Saran saya: Buat tekstur yang mengandung semua bingkai animasi Anda (berdampingan). Ubah koordinat tekstur sesuai dengan bingkai yang ingin Anda tampilkan.
sumber
Anda perlu menggunakan sesuatu yang disebut spritesheet .
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.
sumber
Sprite
kelas. Di dalamSprite
taman 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.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.
sumber