ภาพเคลื่อนไหวสไปรต์ใน openGL


9

ฉันกำลังประสบปัญหาในการนำแอนิเมชั่นสไปรท์มาใช้ใน openGL ES ฉัน googled มันและสิ่งเดียวที่ฉันได้รับคือการสอนการใช้งานผ่าน Canvas

ฉันรู้วิธี แต่ฉันมีปัญหาในการใช้งาน

สิ่งที่ฉันต้องการ: ภาพเคลื่อนไหวสไปรต์ในการตรวจจับการชน

ฉันทำอะไร: ฟังก์ชั่นตรวจจับการชนกันทำงานได้อย่างถูกต้อง

PS: ทุกอย่างทำงานได้ดี แต่ฉันต้องการใช้แอนิเมชั่นใน OPENGL เท่านั้น Canvas จะไม่ทำงานในกรณีของฉัน

------------------------ แก้ไข -----------------------

ตอนนี้ฉันมีแผ่นสไปรต์พูดข้างล่างมีพิกัดบางอย่าง แต่ผู้ประสานงาน (u, v) จะเริ่มจากที่ไหน? ฉันควรพิจารณาคุณ, 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 ฉันมีแผ่นสไปรต์
Siddharth-Verma

1
@ Mr.Beast ฉันรู้ว่าพวกเขาไม่มีอะไรเกี่ยวข้องกัน เป้าหมายของฉันเพื่อให้บรรลุภาพเคลื่อนไหวสไปรต์หลังจากการปะทะกัน จนถึงตอนนี้ฉันสามารถตรวจจับการชนกันของข้อมูลได้ แต่เท่าที่เป็นไปได้นิเมชั่นสไปรต์ .. ฉันไม่สามารถทำได้ PS: ฉันเป็นมือใหม่สำหรับ openGL ES และที่นี่ด้วย .. ขออภัยสำหรับความคิดเห็นของฉันถ้ามี
Siddharth-Verma

@Sid ทำไมคุณมี x / y มั่ว :( 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)

2nd (0.5, 0) (1, 0.5)

ที่ 3 (0, 0.5) (0.5, 1)

ที่ 4 (0.5, 0.5) (1, 1)

ด้วย glTexCoordPointer คุณควรแมปเฟรมที่ 1 ของ quad จากนั้นเมื่อคุณต้องการแสดงเฟรมที่ 2 ที่คุณเรียกว่า glTranslatef (0.5, 0, 0), glTranslatef (0, 0.5, 0) สำหรับ 3rd และ glTranslatef (0.5, 0.5, 0 ) สำหรับวันที่ 4

โค้ดข้างต้นผ่านการทดสอบและทำงานได้ดีมากฉันหวังว่าตัวอย่างจะชัดเจนเพียงพอ


แก้ไข:

ในตอนท้ายของฟังก์ชั่นการวาดของคุณคุณควรรีเซ็ต matrix matrix ของคุณเล็กน้อยรหัสนี้

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 สไปรท์) การเปลี่ยนค่าเป็น 200ms ทุกครั้ง สมมติว่าคุณมีสไปรต์ของคุณจากซ้ายไปขวาและจากบนลงล่างกว่าที่คุณสามารถหาพิกัดเฟรมของคุณในพื้นที่ยูวีทำเช่นนี้

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


ฉันกำลังใช้แถบสามเหลี่ยมที่นี่ ดังนั้นมันจะทำงานในกรณีนี้หรือไม่?
Siddharth-Verma

มีอีกอย่างหนึ่ง .. ฉันควรเก็บพิกัดไว้ในลักษณะใด ----> 1D array ----> อาร์เรย์ 2 มิติ? ถ้า 1D แล้วผู้ประสานงานทั้งหมดควรพิจารณาอะไรในอาเรย์?
Siddharth-Verma

@Sid ใช่มันเป็นสิ่งเดียวกันคุณเพียงแค่ต้องใช้พิกัดแผนที่ UV ที่ถูกต้อง ลองปรับข้อมูลโค้ดของฉันให้ดีกว่าถ้าคุณต้องการความช่วยเหลือเพิ่มเติมในการโพสต์โค้ดของคุณ
Marco Martinelli

@Sid UV พิกัดสำหรับ 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; โดยวิธีที่ฉันคิดว่าเรากำลังจะไปที่ OT คำถามดั้งเดิมได้รับคำตอบบางทีคุณควรปิดอันนี้แล้วเปิดอันใหม่ถ้าจำเป็น
Marco Martinelli

1

คำแนะนำของฉัน: สร้างพื้นผิวที่มีเฟรมภาพเคลื่อนไหวของคุณทั้งหมด (เคียงข้างกัน) เปลี่ยนพิกัดพื้นผิวตามเฟรมที่คุณต้องการแสดง


เสร็จครึ่งหนึ่งแล้ว แต่ฉันจะทำให้ส่วนนี้สำเร็จได้อย่างไร ... "เปลี่ยนพิกัดพื้นผิวตามเฟรมที่คุณต้องการแสดง" PS: ฉันเป็นมือใหม่กับ openGL ES
Siddharth-Verma

1

คุณจำเป็นต้องใช้สิ่งที่เรียกว่าspritesheet

ป้อนคำอธิบายรูปภาพที่นี่

Spritesheet เป็นเพียงภาพเดียวที่มี "เฟรม" ที่แตกต่างกันทั้งหมดที่แสดงท่าทางที่ตัวละครสามารถรับได้ คุณเลือก "เฟรม" ของแผ่นสไปรต์เพื่อแสดงตามเวลา (สำหรับภาพเคลื่อนไหวการระเบิด) หรืออินพุตของผู้เล่น (เช่นหันซ้ายขวาหรือวาดปืน)

ง่ายที่สุดวิธีที่จะทำบางสิ่งบางอย่างเช่นนี้คือการมีสไปรท์ที่เกี่ยวข้องทั้งหมดจะมีขนาดเดียว (ความกว้างและความสูงเดียวกัน) และเพื่อให้ได้รับ (U) พิกัดของเทพดาที่ 4 (sprite_width*4.0 / sprite_sheet_width)จากซ้ายเป็นเพียง

หากคุณพยายามปรับให้เหมาะสมและมีพื้นที่ว่างอย่างมีประสิทธิภาพคุณสามารถใช้เครื่องมือเช่นTexturePackerเพื่อจัดเรียงสไปรต์ของคุณลงในแผ่นงานแผ่นเดียว TexturePacker ยังปล่อยข้อมูล json หรือ xml ที่อธิบายตำแหน่ง xy ของแต่ละ sprites ที่คุณโหลด


ฉันมีแผ่นสไปรต์แล้ว ฉันรู้วิธีการโดยการเปลี่ยนพิกัด แต่คำถามหลักของฉันคือ "ทำอย่างไรถึงจะบรรลุเป้าหมายนี้คือ openGL ES" คุณมีโค้ดหลอกหรือโค้ดจาวาสำหรับสิ่งนี้หรือไม่? อัลกอริทึมอาจใช้งานได้สำหรับฉัน
Siddharth-Verma

2
เขียนSpriteชั้นเรียน ภายในSpriteคลาสอุทยานรายการของคู่ (u, v) ที่อธิบายถึงพิกัด (u, v) ของแต่ละ "นิ่ง" ในพื้นผิว คุณต้องมีตัวแปรอีก 2 ตัวเพื่อติดตามเวลา: หนึ่งโฟลตเพื่อเก็บ "วินาทีต่อเฟรม" (# วินาทีเพื่อใช้ในแต่ละเฟรมแอนิเมชั่น) และโฟลตอีกอันที่เรียกว่า "นาฬิกา" ซึ่งเก็บ "เวลาปัจจุบัน" ในวงจรภาพเคลื่อนไหว เมื่อคุณวาดรูปคุณต้องอัปเดตเวลาปัจจุบัน เมื่อเกิน "วินาทีต่อเฟรม" คุณเลื่อนไปยังเฟรมถัดไปของภาพเคลื่อนไหวเพื่อให้ภาพเคลื่อนไหวเคลื่อนไหว
bobobobo

ตกลงดังนั้นรายการที่มีคู่ (u, v) จะเป็นอาร์เรย์ 2d หรือไม่
Siddharth-Verma

โปรดดูคำถามที่แก้ไขแล้ว
Siddharth-Verma

1

คุณสามารถใช้I_COLLIDEกับ OpenGL

กำหนดให้แต่ละเอนทิตีในโลกเป็นกล่องจากนั้นตรวจสอบว่าแต่ละแกนของกล่องชนกับเอนทิตี้อื่นหรือไม่

ด้วยเอนทิตีจำนวนมากเพื่อทดสอบการชนคุณอาจต้องการเช็คอินที่แปด คุณจะแบ่งโลกออกเป็นเซ็กเตอร์อย่างง่าย ๆ จากนั้นตรวจสอบการชนกันของวัตถุในเซกเตอร์เดียวกันเท่านั้น

นอกจากนี้ยังใช้เครื่องยนต์ Bullet Bullet ซึ่งเป็นระบบตรวจจับการชนแบบโอเพนซอร์สและเครื่องมือฟิสิกส์


การตรวจจับการชนกันได้รับความสำเร็จ เป้าหมายของฉันคือการสร้างภาพเคลื่อนไหวสไปรต์
Siddharth-Verma
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.