Tengo problemas para implementar la animación de sprites en openGL ES. Lo busqué en Google y lo único que obtengo es el Tutorial que se implementa a través de Canvas.
Conozco el camino pero tengo problemas para implementarlo.
Lo que necesito: una animación de sprites sobre detección de colisiones.
Lo que hice: la función de detección de colisión funciona correctamente.
PD: Todo funciona bien, pero quiero implementar la animación SOLO en OPENGL. El lienzo no funcionará en mi caso.
------------------------ EDITAR -----------------------
Ahora tengo una hoja de sprites, digamos que la siguiente tiene algunas coordenadas determinadas, pero ¿desde dónde comenzarán las coordenadas (u, v)? ¿Debo considerar mis coordenadas u, v desde (0,0) o desde (0,5) y en qué patrón debo almacenarlas en mi lista ...? ----> De izquierda a derecha O ----> de arriba a abajo
¿Necesito tener una matriz 2D en mi clase de sprites? Aquí está la imagen para una mejor comprensión.
Supongo que tengo una hoja de sprites NxN, donde N = 3,4,5,6, ... y así sucesivamente.
.
.
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();
}
}
Respuestas:
Este es un fragmento de código que estoy usando en mi aplicación de Android.
El truco aquí es usar glMatrixMode seguido de glTranslatef. Eso te permitirá traducir el espacio ultravioleta.
el rango de coordenadas uv varía de (0,0) a (1,1)
Supongamos que tiene una textura cuadrada con 4 cuadros y desea texturizar un quad. Usaré las siguientes coordenadas para definir marcos en el espacio uv (la elección depende de usted)
1er (0, 0) (0.5, 0.5)
2do (0.5, 0) (1, 0.5)
3er (0, 0.5) (0.5, 1)
4to (0.5, 0.5) (1, 1)
Con glTexCoordPointer debe asignar el primer fotograma en su quad y luego, cuando desee mostrar el segundo fotograma, llame a glTranslatef (0.5, 0, 0), glTranslatef (0, 0.5, 0) para el tercero y glTranslatef (0.5, 0.5, 0 ) para el 4to.
El código anterior está probado y funciona muy bien, espero que el ejemplo sea lo suficientemente claro.
EDITAR:
Al final de su función de dibujo, debe restablecer su matriz de textura con este código.
ok, tomemos 5 filas y 4 columnas como ejemplo. Hay un máximo de 20 sprites en su conjunto de sprites, así que use int idx = (int) ((System.currentTimeMillis ()% 200 * number_of_sprites))) / 200);
idx ahora va de 0 a number_of_sprites-1 (puede ser <20 si tiene, por ejemplo, 5 filas, 4 columnas pero solo 18 sprites) cambiando su valor cada 200 ms. Suponiendo que tiene su sprite de izquierda a derecha y de arriba a abajo, puede encontrar su coordenada de marco en el espacio uv haciendo esto.
cuando haces idx% c encuentras el índice de tu columna, los resultados siempre están entre 0 y c-1
idx% c es un número entero, necesita escalarlo a un valor entre 0.0 y 1.0 para dividirlo por cf, cf es un flotante, por lo que aquí hay una conversión implícita
idx / c es lo mismo pero para las filas, idx y c son ambos enteros, por lo que el resultado sigue siendo entero, y es el índice de la fila, dividiendo entre rf obtienes un valor entre 0.0 y 1.0
fuente
int oldIdx;
antes depublic FragileSquare()
eso en el método de dibujo, haga esto:int idx = oldIdx==(numberSprites-1) ? (numberSprites-1) : (int)((System.currentTimeMillis()%(200*numberSprites))/200); oldIdx = idx;
Por cierto, creo que vamos a OT, la pregunta original fue respondida, tal vez debería cerrar esta y abrir una nueva si es necesario.Mi sugerencia: cree una textura que contenga todos los cuadros de su animación (uno al lado del otro). Cambie las coordenadas de textura de acuerdo con el marco que desea mostrar.
fuente
Necesitas usar algo llamado una hoja de sprites .
Una hoja de sprites es solo una imagen con todos los diferentes "cuadros" que muestran las poses que el personaje puede tomar. Usted selecciona qué "marco" de la hoja de sprites para mostrar, ya sea en función del tiempo (como para una animación de explosión) o de la entrada del jugador (como mirar hacia la izquierda, derecha o dibujar un arma)
La forma más fácil de hacer algo como esto es hacer que todos los sprites relacionados tengan el mismo tamaño (mismo ancho y altura), y así obtener la coordenada (u) del 4to sprite desde la izquierda es justo
(sprite_width*4.0 / sprite_sheet_width)
.Si está tratando de optimizar y ahorrar espacio, puede usar una herramienta como TexturePacker para empacar sus sprites en una sola hoja. TexturePacker también emite datos json o xml que describen las ubicaciones xy de cada uno de los sprites en los que carga.
fuente
Sprite
clase. Dentro de laSprite
clase, estacione una lista de pares (u, v) que describen las coordenadas (u, v) de cada "imagen fija" en la textura. Necesita 2 variables más para rastrear el tiempo: un flotador para almacenar "segundos por cuadro" (# segundos para gastar en cada cuadro de animación) y otro flotante llamado "reloj", que almacena el "tiempo actual" en el ciclo de animación. Cuando vaya a dibujar, debe actualizar la hora actual. Cuando se exceden los "segundos por fotograma", pasa al siguiente fotograma de la animación, de modo que la animación continúa.Puede usar I_COLLIDE con OpenGL.
Haga que cada entidad en el mundo sea una caja, luego verifique si cada uno de los ejes de la caja está colisionando con otras entidades.
Con grandes cantidades de entidades para detectar colisiones, es posible que desee registrarse en un octree. Simplemente dividiría el mundo en sectores, luego solo verificaría la colisión entre objetos en los mismos sectores.
También utilice el motor de dinámica Bullet, que es un motor de física y detección de colisiones de código abierto.
fuente