hoạt hình sprite trong openGL


9

Tôi đang gặp vấn đề khi triển khai hoạt hình sprite trong openGL ES. Tôi đã googled nó và điều duy nhất tôi nhận được là Hướng dẫn triển khai qua Canvas.

Tôi biết cách nhưng tôi đang gặp vấn đề trong việc thực hiện nó.

Những gì tôi cần: Một hình ảnh động trên phát hiện va chạm.

Những gì tôi đã làm: Chức năng Phát hiện Va chạm hoạt động đúng.

PS: Mọi thứ đều hoạt động tốt nhưng tôi muốn triển khai hình động trong CHỈ OPENGL. Canvas sẽ không hoạt động trong trường hợp của tôi.

------------------------ BIÊN TẬP-----------------------

Bây giờ tôi có một bảng sprite, giả sử bảng dưới đây có một số tọa độ nhất định, nhưng từ đó tọa độ (u, v) sẽ bắt đầu từ đâu? Tôi nên xem xét u của mình, v tọa độ từ (0,0) hoặc từ (0,5) và trong mẫu nào tôi nên lưu trữ chúng trong danh sách của mình ..? ----> Từ trái sang phải HOẶC ----> từ trên xuống dưới

Tôi có cần phải có một mảng 2D trong lớp họa tiết của mình không? đây là hình ảnh để hiểu rõ hơn

Tấm Sprite Tôi giả sử rằng tôi có một bảng sprite NxN, trong đó N = 3,4,5,6, .... và cứ thế.

.

.

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
Hoạt hình Sprite và phát hiện va chạm không liên quan gì đến nhau.
API-Beast

Bạn muốn loại hoạt hình nào? Bộ xương, tấm sprite, cái gì khác?
GameDev-er

@ GameDev-er Tôi có một bảng sprite.
Siddharth-Verma

1
@ Mr.Beast Tôi biết họ không liên quan gì đến nhau. Mục đích của tôi để đạt được hoạt hình sprite sau khi va chạm. Cho đến bây giờ tôi có thể đạt được phát hiện va chạm. Nhưng khi có liên quan đến hoạt hình sprite .. tôi không thể làm điều đó. PS: Tôi là người mới chơi openGL ES và ở đây cũng vậy .. rất xin lỗi vì bất kỳ nhận xét nào của tôi, nếu có.
Siddharth-Verma

@Sid Tại sao bạn có x / y lẫn lộn? :( X là trục hoành. (Tôi biết nó không phải là vốn có nhưng đó là một quy ước mà người ta không nên chống lại)
doppelgreener

Câu trả lời:


6

Đây là đoạn mã tôi đang sử dụng trong ứng dụng Android của mình.

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

Mẹo ở đây là sử dụng glMatrixMode theo sau là glTranslatef. Điều đó sẽ cho phép bạn dịch không gian uv.

tọa độ uv nằm trong khoảng từ (0,0) đến (1,1)

Giả sử bạn có một kết cấu bình phương với 4 khung hình và bạn muốn kết cấu một hình tứ giác. Tôi sẽ sử dụng các tọa độ sau để xác định khung trong không gian uv (sự lựa chọn tùy thuộc vào bạn)

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

Thứ 2 (0,5, 0) (1, 0,5)

Thứ 3 (0, 0,5) (0,5, 1)

Thứ 4 (0,5, 0,5) (1, 1)

Với glTexCoordPulum, bạn nên ánh xạ khung thứ 1 trên quad của mình sau đó khi bạn muốn hiển thị khung thứ 2, bạn gọi glTranslatef (0.5, 0, 0), glTranslatef (0, 0.5, 0) cho thứ 3 và glTranslatef (0.5, 0.5, 0 ) cho lần thứ 4.

Đoạn mã trên được kiểm tra và hoạt động rất tốt, tôi hy vọng ví dụ này đủ rõ ràng.


BIÊN TẬP:

ở cuối chức năng vẽ của bạn, bạn nên đặt lại ma trận kết cấu của mình bằng mã này.

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

ok, hãy lấy 5 hàng và 4 cột làm ví dụ. Có tối đa 20 sprite trong spiteset của bạn, vì vậy hãy sử dụng int idx = (int) ((System.cienTimeMillis ()% 200 * number_of_sprites)) / 200);

idx hiện chuyển từ 0 sang number_of_sprites-1 (có thể <20 nếu bạn có ví dụ 5 hàng, 4 cột nhưng chỉ có 18 sprite) thay đổi giá trị của nó sau mỗi 200ms. Giả sử bạn có sprite của bạn từ trái sang phải và từ trên xuống dưới, bạn có thể tìm thấy tọa độ khung của mình trong không gian uv làm điều này.

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

Khi bạn thực hiện idx% c, bạn tìm thấy chỉ mục cột của mình, kết quả luôn nằm trong khoảng từ 0 đến c-1

idx% c là một số nguyên, bạn cần chia tỷ lệ thành giá trị trong khoảng từ 0,0 đến 1,0 để bạn chia cho cf, cf là một số float nên có một biểu tượng ẩn ở đây

idx / c là cùng một thứ nhưng đối với các hàng, idx và c đều là số nguyên nên kết quả vẫn là số nguyên và đó là chỉ số hàng, chia cho rf bạn nhận được giá trị từ 0,0 đến 1,0


Tôi đang sử dụng một dải tam giác ở đây. Vì vậy, nó sẽ làm việc trong trường hợp này?
Siddharth-Verma

Một điều nữa .. tôi nên lưu trữ tọa độ theo cách nào? ----> mảng 1D ----> mảng 2D? Nếu 1D, thì tất cả các tọa độ tôi nên xem xét trong mảng là gì?
Siddharth-Verma

@Sid Vâng, đó là điều tương tự, bạn chỉ cần sử dụng tọa độ ánh xạ uv đúng. Cố gắng điều chỉnh đoạn mã của tôi hơn nếu bạn cần thêm trợ giúp đăng mã của mình
Marco Martinelli

@Sid tọa độ UV cho glTexCoordPulum cần được lưu trữ trong mảng 1D
Marco Martinelli

1
Đối với vấn đề thứ nhất tôi không biết, nó hoạt động tốt ở đây, đối với vấn đề thứ hai, bạn cần dừng idx để quay về 0 nên một mẹo đơn giản là đây. Khai báo một biến int oldIdx;trước public FragileSquare()đó trong phương thức vẽ thực hiện điều này: int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx; Theo cách tôi nghĩ rằng chúng ta đang đi OT, câu hỏi ban đầu đã được trả lời, có lẽ bạn nên đóng cái này và mở cái mới nếu cần.
Marco Martinelli

1

Đề xuất của tôi: Tạo kết cấu chứa tất cả các khung hình động của bạn (cạnh nhau). Thay đổi tọa độ kết cấu theo khung bạn muốn hiển thị.


Một nửa trong số đó đã được thực hiện. Nhưng làm thế nào để tôi đạt được phần này ...... "Thay đổi tọa độ kết cấu theo khung bạn muốn hiển thị." PS: Tôi là người mới chơi openGL ES.
Siddharth-Verma

1

Bạn cần phải sử dụng một cái gì đó gọi là một spritesheet .

nhập mô tả hình ảnh ở đây

Một spritesheet chỉ là một hình ảnh duy nhất với tất cả các "khung" khác nhau cho thấy các tư thế mà nhân vật có thể thực hiện. Bạn chọn "khung" nào của bảng sprite để hiển thị dựa trên thời gian (như đối với hoạt hình vụ nổ) hoặc trên đầu vào của người chơi (chẳng hạn như quay mặt sang trái, phải hoặc vẽ súng)

Các đơn giản nhất cách để làm một cái gì đó như thế này là phải có tất cả các sprites có liên quan có cùng kích thước (cùng chiều rộng và chiều cao), và do đó nhận được (u) phối hợp của ma thứ 4 từ bên trái chỉ là (sprite_width*4.0 / sprite_sheet_width).

Nếu bạn đang cố gắng tối ưu hóa và tiết kiệm không gian, bạn có thể sử dụng một công cụ như TexturePacker để đóng gói các họa tiết của bạn lên một trang. TexturePacker cũng phát ra dữ liệu json hoặc xml mô tả các vị trí xy của từng sprite bạn tải vào.


Tôi đã có một tấm sprite. tôi biết phương pháp này, bằng cách thay đổi tọa độ. Nhưng câu hỏi chính của tôi là "Làm thế nào để đạt được điều này là openGL ES?" Bạn có mã giả hay mã java nào không? Thuật toán có thể làm việc cho tôi.
Siddharth-Verma

2
Viết một Spritelớp. Bên trong Spritelớp, một danh sách các cặp (u, v) mô tả tọa độ (u, v) của mỗi "tĩnh" trong kết cấu. Bạn cần thêm 2 biến để theo dõi thời gian: một số float để lưu trữ "giây trên mỗi khung hình" (# giây để dành cho mỗi khung hình động) và một số float khác có tên là "clock", lưu trữ "thời gian hiện tại" trong chu kỳ hoạt hình. Khi bạn đi vẽ, bạn phải cập nhật thời gian hiện tại. Khi vượt quá "giây trên mỗi khung hình", bạn chuyển sang khung hình tiếp theo của hình động, để hình ảnh động tiếp tục.
bobobobo

Được rồi, vậy danh sách chứa các cặp (u, v) sẽ là một mảng 2d?
Siddharth-Verma

xem câu hỏi đã được chỉnh sửa
Siddharth-Verma

1

Bạn có thể sử dụng I_COLLIDE với OpenGL.

Đặt mỗi thực thể trên thế giới thành một hộp, sau đó kiểm tra xem mỗi trục của hộp có va chạm với các thực thể khác không.

Với số lượng lớn các thực thể để kiểm tra va chạm, bạn có thể muốn kiểm tra một octree. Bạn sẽ đơn giản phân chia thế giới thành các lĩnh vực, sau đó chỉ kiểm tra sự va chạm giữa các đối tượng trong cùng các lĩnh vực.

Cũng sử dụng công cụ động lực học Bullet, một công cụ phát hiện va chạm và vật lý nguồn mở.


phát hiện va chạm đã đạt được. Mục đích của tôi là tạo ra một hình ảnh động sprite.
Siddharth-Verma
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.